package com.cq.hd.system.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cq.hd.common.constant.HfConstant;
import com.cq.hd.common.entity.hf.*;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.GenerateUtil;
import com.cq.hd.common.utils.HttpUtils;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Component
public class HuifuConfig {

    public final static String SYS_ID = "6666000144962673";

    public final static String PRODUCT_ID = "PAYUN";

    // 平台收款商户账号
    public final static String SYS_MERCHANT_NO = "6666000146237876";

    // 平台的充值户(会员套餐、次卡费)              A31543304
    public final static String SYS_RECHARGE_ACCOUNT_NO = "A31570832";

    // 平台基本户(消费者下单)
    public final static String SYS_BASE_ACCOUNT_NO = "A31186103";

    // 公钥
    public final static String PUBLIC_SECRET = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtS4DSxPJWBdUNRzyQh6ERIylQG+HLbl/uio8VvSRf55X+1DQFpDPMNilIj+Hi2i7avnDzJn0YWwyIAGEsh6voDUVJsnAfjHpMQbplrZqXtuZhN02zr/89ZASry9pS9nRB0mDkEaGi7QskCacJ7eUj9WunAY3YsgQHG15uRkLK8c2QX7FF9xEplqIBRqUK9d6dLwG4fBOV7sInrhkWDOucJhg9z2w0vi8hkjYJMPWtt9bEiDtobc+QkX6K2TlvJzafHBDC4cLq+hvKysk9K6hP42+pe1QtvSKJBOrgLfhaXvtXIPL0kmXtGg1VVIjkNnzaDISov0iJ2xpKM56KSn8CQIDAQAB";

    // 私钥
    private final static String PRIVATE_SECRET = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC1LgNLE8lYF1Q1HPJCHoREjKVAb4ctuX+6KjxW9JF/nlf7UNAWkM8w2KUiP4eLaLtq+cPMmfRhbDIgAYSyHq+gNRUmycB+MekxBumWtmpe25mE3TbOv/z1kBKvL2lL2dEHSYOQRoaLtCyQJpwnt5SP1a6cBjdiyBAcbXm5GQsrxzZBfsUX3ESmWogFGpQr13p0vAbh8E5XuwieuGRYM65wmGD3PbDS+LyGSNgkw9a231sSIO2htz5CRforZOW8nNp8cEMLhwur6G8rKyT0rqE/jb6l7VC29IokE6uAt+Fpe+1cg8vSSZe0aDVVUiOQ2fNoMhKi/SInbGkoznopKfwJAgMBAAECggEAAiXmghhc9b9pDywlryT/enSUbPwlhSRC4Gkpx/okU3gEIQWnQe07l5+p7YsFR2DZf/4wFRfqLtGCkqCR+y6j9GlMs+YGcziSRDOJx3CoODGwU0PwJ2ldTWgE4LDWNcECWmzDs40ygSuEr7zVcx8ZEs98v3rPY0tt7Xhazhf+6ujvlQ3zFg7Yv46rLuIZQVqzttExQb2PUTHzDDVbhY/aqkOa88P6CThEnGJwi1YbyoEblrw6GiJqsltlEvK8yhqGt6yi79B3m5r1ejTjaARLxx326Ojm/HKTUggadOAXNPGaFvdb/EsEVoZFc0VZyYNvciQu33WZZDMoFQgAWicRJQKBgQD0OjO8EcUobZXCN0rMV6h8RFIctP4x/8NmjBBmImXpI+nipMvsze1KnzgjSNYfGVwCpNGiLsSxjQpECjAkBpKBzUFbPiYo8SOQs7ivdEE9NpZMOh7p41N366E4rNgy2KdgJjfdUz73rlKRcAol/P4XXYi2ZHtQfqctIA0ncSY4cwKBgQC96ct7rXv+G07oN3q7KN888oD0FPRl5Y12h9CbZR+8CQz7EeQocauf0FClxvTsdVnNHKZUOccda7sTQeLN9DToRKWkxVaIbiUMNW6iAv8V0GHbkHCJTlZbfifTsxNhyZACpYKj0hFWCyfE/mL89qCRZBIgujuwxzsXuvjgq6+mkwKBgF8y2Lu0iY+qt7eO6f8hJDHcR82c14ER2077xeCqA+OO9jo8Vqkl1BtEWROX7q8MqYr2SCjZ5h33hkrjVcSVM0KZiaJRZXqMFHrxM0phHJUJ1Cg+d5Jf5EdYd+2polSfkw6tlxUUv/S35MOAUtRf+4OMGCBQpqjH1c6HMdlwB5/1AoGAPfa1TLIq/ZrdYQkRA1XvmIwrJPhdUY3XXTAtETaqZwiw8o5A2i1UaP1oAt7qdOhJF5JcdqivXdsTm9HodXhTduFHBn7YoAUIE3avlS7TGcP22dPD1Bj6NjnwNrN8BHDmiuaDvH3C6EcVf8HcfFrfwvBatdDtvt0SW8jGgU+jLP8CgYAKl/DZdIZx2rFFhBagIVjZiQzRf/kDNw0VEieiU3Ts72TST/KYEg54amHOSklDRrNHUz7dlCa0Ne9daFVcAhAjn07S1ky+jK4hjGL5weFze+HNVzbImVzsK8nmacZJUpgl7KekT1fgzLHp6lWz2EV5IAUZHzahSIuUDgEwU3wPHA==";

    // 汇付公钥
    private final static String HF_PUBLIC_SECRET = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAinj8rqBTWfC+epokekqUM+w/RC+27n5ZfsM+V52X38tMrN3vRcYeVSaTRBkuBEmyMd4ASTycKWZF6YKvFy2OxiycSWH+euEPJoL/jGBaut+SavsxOv0pUN9Zh+61lCKXhmfortu/tKSPSEUEfw31eSvOnwwP0sTtM99PSY031WUShn/K8cMC1eit19sjk5GCSbf/0JHK6DG4LPvacGSIJK2qEzXRJtjXSAUF65qgYGe76kNHVfPTPAonqC2jxQeYEkSSMVSHejswkVIcOgmFuyHTadjyO4p8ociKdcalWZgBvy8vphRVIL+gFjc9vmWP0lVmJQnEiP4ki0w63d4uqwIDAQAB";


    // 图片上传
    private final static String IMG_UPLOAD_API = "https://api.huifu.com/v2/supplementary/picture";

    // 企业商户基本信息入驻
    private final static String MERCHANT_ENT_API = "https://api.huifu.com/v2/merchant/basicdata/ent";

    // 子账号开通
    private final static String MERCHANT_SETTLE_CONFIG_API = "https://api.huifu.com/v2/merchant/settle/config";

    // 修改子账户配置
    private final static String MERCHANT_SETTLE_MODIFY_API = "https://api.huifu.com/v2/merchant/settle/modify";

    // 账户余额信息查询（查询基本户和现金户）
    private final static String ACCT_BALANCE_QUERY_API = "https://api.huifu.com/v2/trade/acctpayment/balance/query";

    // 用户信息查询
    private final static String USER_BASIC_DATA_QUERY_API = "https://api.huifu.com/v2/user/basicdata/query";

    // 个人商户基本信息入驻
    private final static String MERCHANT_INDV_API = "https://api.huifu.com/v2/merchant/basicdata/indv";

    // 商户基本信息修改
    private final static String MERCHANT_BASIC_DATA_MODIFY = "https://api.huifu.com/v2/merchant/basicdata/modify";

    // 商户业务开通
    private final static String MERCHANT_OPEN_API = "https://api.huifu.com/v2/merchant/busi/open";

    // 商户业务开通修改
    private final static String MERCHANT_OPEN_MODIFY_API = "https://api.huifu.com/v2/merchant/busi/modify";

    // 申请单查询    调用此接口查询商户申请单审核状态及各业务开通结果。支持查询商户各种已提交的申请单，包括商户业务开通申请单、活动报名申请单、信息修改申请单等，若申请单审核拒绝，将返回拒绝的详细原因，可根据拒绝原因修改信息
    private final static String BASIC_STATUS_QUERY_API = "https://api.huifu.com/v2/merchant/basicdata/status/query";

    // 微信商户配置
    private final static String WX_BUSINESS_CONFIG_API = "https://api.huifu.com/v2/merchant/busi/config";

    // 微信实名认证状态查询
    private final static String WX_BUSINESS_REAL_QUERY_API = "https://api.huifu.com/v2/merchant/busi/realname/query";

    // 商户详细信息查询（查询合同签约状态）
    private final static String MERCHANT_BASIC_DATA_QUERY_API = "https://api.huifu.com/v2/merchant/basicdata/query";

    // 网银支付
    private final static String BANK_PAY_API = "https://api.huifu.com/v2/trade/onlinepayment/banking/frontpay";

    // 线上交易查询
    private final static String BANK_PAY_QUERY_API = "https://api.huifu.com/v2/trade/onlinepayment/query";

    // 聚合正扫
    private final static String JS_PAY_API = "https://api.huifu.com/v2/trade/payment/jspay";

    // 微信小程序预下单
    private final static String PRE_ORDER_API = "https://api.huifu.com/v2/trade/hosting/payment/preorder";

    // 交易查询
    private final static String TRADE_QUERY_API = "https://api.huifu.com/v2/trade/payment/scanpay/query";

    // 交易退款
    private final static String TRADE_REFUND_API = "https://api.huifu.com/v2/trade/payment/scanpay/refund";

    // 交易退款查询
    private final static String TRADE_REFUND_QUERY_API = "https://api.huifu.com/v2/trade/payment/scanpay/refundquery";

    // 个人用户开户（邀请经纪人入驻需要）
    private final static String AGENT_USER_INVITE_API = "https://api.huifu.com/v2/user/basicdata/indv";

    // 用户业务入驻
    private final static String AGENT_USER_OPEN_API = "https://api.huifu.com/v2/user/busi/open";

    // 用户业务入驻修改
    private final static String AGENT_USER_MODIFY_API = "https://api.huifu.com/v2/user/busi/modify";

    // 用户业务查询
    private final static String AGENT_USER_QUERY_API = "https://api.huifu.com/v2/user/basicdata/query";

    // 个人签约发起
    private final static String AGENT_SIGN_CREATE_API = "https://api.huifu.com/v2/hyc/personsign/create";

    // 个人签约状态查询
    private final static String AGENT_SIGN_QUERY_API = "https://api.huifu.com/v2/hyc/contract/query";

    // 商户签约查询
    private final static String MERCHANT_SIGN_QUERY_API = "https://api.huifu.com/v2/hyc/mersign/query";

    // 余额支付（给商户分本金）
    private final static String TRADE_ACCOUNT_AMT_PAY_API = "https://api.huifu.com/v2/trade/acctpayment/pay";

    // 补贴转账（给商户分补贴）
    private final static String TRADE_MARKET_TRANSFER_PAY_API = "https://api.huifu.com/v2/trade/marketing/transfer/pay";

    // 补贴转账查询
    private final static String TRADE_MARKET_TRANSFER_QUERY_API = "https://api.huifu.com/v2/trade/marketing/transfer/query";

    // 余额支付查询
    private final static String TRADE_ACCOUNT_AMT_PAY_QUERY_API = "https://api.huifu.com/v2/trade/acctpayment/pay/query";

    // 余额支付退款
    private final static String TRADE_ACCOUNT_AMT_REFUND_API = "https://api.huifu.com/v2/trade/acctpayment/refund";

    // 余额支付退款查询
    private final static String TRADE_ACCOUNT_AMT_REFUND_QUERY_API = "https://api.huifu.com/v2/trade/acctpayment/refund/query";

    // 结算提现
    private final static String SETTLEMENT_API = "https://api.huifu.com/v2/trade/settlement/enchashment";

    // 出金交易查询
    private final static String SETTLEMENT_QUERY_API = "https://api.huifu.com/v2/trade/settlement/query";

    // 交易、结算文件查询
    private final static String SETTLEMENT_CHECK_FILE_QUERY_API = "https://api.huifu.com/v2/trade/check/filequery";

    // 账务流水查询
    private final static String TRADE_ACCOUNT_AMT_PAY_LOG_QUERY_API = "https://api.huifu.com/v2/trade/acctpayment/acctlog/query";

    // 开票类目查询
    private final static String HYC_INV_CATEGORY_QUERY_API = "https://api.huifu.com/v2/hyc/invcategory/query";

    // 申请开票（灵活用工）
    private final static String HYC_INVOICE_APPLY_API = "https://api.huifu.com/v2/hyc/invoice/apply";

    // 开票信息查询
    private final static String HYC_INVOICE_QUERY_API = "https://api.huifu.com/v2/hyc/invinfo/query";

    // 业务模式说明
    private final static String BUSINESS_INSTRUCTION = "商圈邀请商户入驻到平台，为商圈提供商户商品，商圈组合商户商品在平台以团购形式售卖，消费者下单后，到店核销，核销完成，将商户所得结算给商户。";
    // 资金流向说明
    private final static String CAPITAL_INSTRUCTION = "1、用户购买团购券支付到平台，核销后，平台根据结算周期，结算给商户；2、商圈充值补贴到营销账户，活动结束后，根据商户实际核销订单，将补贴结算给商户。";
    // 功能开通用途说明
    private final static String FUNCTION_INSTRUCTION = "用于将消费者支付的订单金额及商圈充值的补贴金额结算给商户。";

    @Autowired
    private WxConfig staticWxConfig;

    private static WxConfig wxConfig;

    @PostConstruct
    public void init() {
        wxConfig = staticWxConfig;
    }

    // 用户信息查询
    public static String userBasicDataQueryApi(String hfId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 商户汇付id
        dataMap.put("huifu_id", hfId);
        // 请求流水号
        dataMap.put("req_seq_id", yyyyMMddHHmmss);
        // 请求日期
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("USER_BASIC_DATA_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(USER_BASIC_DATA_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("USER_BASIC_DATA_QUERY_API-result:{}", result);

            return result;
        } catch (Exception e) {
            log.error("调用用户信息查询接口失败", e);
        }

        return "";
    }

    // 账户余额信息查询
    public static String acctBalanceQueryApi(String hfId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 商户汇付id
        dataMap.put("huifu_id", hfId);
        // 请求流水号
        dataMap.put("req_seq_id", yyyyMMddHHmmss);
        // 请求日期
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("ACCT_BALANCE_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(ACCT_BALANCE_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("ACCT_BALANCE_QUERY_API-result:{}", result);

            return result;
        } catch (Exception e) {
            log.error("调用账户余额信息查询接口失败", e);
        }

        return "";
    }

    // 开票信息查询
    public static String hycInvQueryApi(HfInvApply hfInvApply) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 商户汇付id
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        // 请求流水号
        dataMap.put("req_seq_id", yyyyMMddHHmmss);
        // 请求日期
        dataMap.put("req_date", yyyyMMdd);
        // 开票批次号
        dataMap.put("invoice_batch", hfInvApply.getInvoiceBatch());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("HYC_INVOICE_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(HYC_INVOICE_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("HYC_INVOICE_QUERY_API-result:{}", result);

            return result;
        } catch (Exception e) {
            log.error("调用开票信息查询接口失败", e);
        }

        return "";
    }

    // 申请开票
    public static HfInvApply hycInvApplyApi(HfInvApply hfInvApply) {
        hfInvApply.setHuifu_id(SYS_MERCHANT_NO);
        // 开票类目
        hfInvApply.setInvoiceCategory("现代服务*市场推广费");
        // 发票类型:1:增值税普票；2:增值税专票
        hfInvApply.setInvoiceType("2");
        hfInvApply.setReceiveMobile("18206008999");
        hfInvApply.setReceiveName("张宇航");
        hfInvApply.setCourierAddress("18206008999@163.com");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 商户汇付id
        dataMap.put("huifu_id", hfInvApply.getHuifu_id());
        // 请求流水号
        dataMap.put("req_seq_id", hfInvApply.getReqSeqId());
        // 请求日期
        dataMap.put("req_date", hfInvApply.getReqDate());

        List<Map<String, String>> batchMapList = new ArrayList<>();
        List<HfInvApplyBatch> batchList = hfInvApply.getBatchList();
        for (HfInvApplyBatch hfInvApplyBatch : batchList) {
            Map<String, String> map = new HashMap<>();
            map.put("trans_date", hfInvApplyBatch.getTransDate());
            map.put("trans_seq_id", hfInvApplyBatch.getTransSeqId());
            batchMapList.add(map);
        }

        // 交易流水列表
        dataMap.put("batch_list", batchMapList);
        // 接收人手机号
        dataMap.put("receive_mobile", hfInvApply.getReceiveMobile());
        // 接收人姓名
        dataMap.put("receive_name", hfInvApply.getReceiveName());
        // 快递地址
        dataMap.put("courier_address", hfInvApply.getCourierAddress());
        // 开票类目
        dataMap.put("invoice_category", hfInvApply.getInvoiceCategory());
        // 发票类型
        dataMap.put("invoice_type", hfInvApply.getInvoiceType());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("HYC_INVOICE_APPLY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(HYC_INVOICE_APPLY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("HYC_INVOICE_APPLY_API-result:{}", result);
            hfInvApply.setResult(result);
        } catch (Exception e) {
            log.error("调用申请开票（灵活用工）接口失败", e);
        }

        return hfInvApply;
    }

    // 开票类目查询
    public static String hycInvCategoryQueryApi(String minorAgentId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 落地公司机构号
        dataMap.put("minor_agent_id", minorAgentId);
        // 请求流水号
        dataMap.put("req_seq_id", yyyyMMddHHmmss);
        // 请求日期
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("HYC_INV_CATEGORY_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(HYC_INV_CATEGORY_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("HYC_INV_CATEGORY_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用开票类目查询接口失败", e);
        }

        return "";
    }

    // 出金交易查询
    public static String settlementQueryApi(HfSettlement hfSettlement) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 取现方ID号
        dataMap.put("huifu_id", hfSettlement.getHfId());
        // 原交易请求日期
        dataMap.put("org_req_date", hfSettlement.getOrgReqDate());
        // 原交易请求流水号
        dataMap.put("org_req_seq_id", hfSettlement.getOrgReqSeqId());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("SETTLEMENT_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(SETTLEMENT_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("SETTLEMENT_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用结算提现查询接口失败", e);
        }

        return "";
    }

    // 结算提现
    public static String settlementApi(HfSettlement hfSettlement) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        BigDecimal cashAmtBig = new BigDecimal(hfSettlement.getCashAmt());
        if (cashAmtBig.compareTo(BigDecimal.ZERO) <= 0) {
            Throw.isBusinessException("金额不能小于等于0");
        }

        String cashAmt = new DecimalFormat("0.00").format(cashAmtBig);

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfSettlement.getReqSeqId());
        dataMap.put("req_date", hfSettlement.getReqDate());
        // 取现金额	单位元，需保留小数点后两位
        dataMap.put("cash_amt", cashAmt);
        // 取现方ID号
        dataMap.put("huifu_id", hfSettlement.getHfId());
        // 账户号（现金户）
        String actId = hfSettlement.getActId();
        if (!StringUtils.isBlank(actId)) {
            dataMap.put("acct_id", actId);
        }

        // 到账日期类型	D0：当日到账；当日交易资金当天可取现到账；T1：次工作日到账；D1：次自然日到账；DM：当日到账；到账资金不包括当天的交易资金；
        dataMap.put("into_acct_date_type", "T1");
        // 取现卡序列号
        dataMap.put("token_no", hfSettlement.getTokenNo());

        // 异步通知地址（走定时任务扫描）
//        dataMap.put("notify_url", HfConstant.SETTLEMENT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("SETTLEMENT_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(SETTLEMENT_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("SETTLEMENT_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用结算提现接口失败", e);
        }

        return "";
    }

    // 补贴转账查询
    public static String tradeMarketTransferQueryApi(HfTradeMarketPay hfTradeMarketPay) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfTradeMarketPay.getReqSeqId());
        dataMap.put("req_date", hfTradeMarketPay.getReqDate());
        // 原请求流水号
        dataMap.put("org_req_seq_id", hfTradeMarketPay.getOrgReqSeqId());
        // 原请求日期
        dataMap.put("org_req_date", hfTradeMarketPay.getOrgReqDate());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_MARKET_TRANSFER_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_MARKET_TRANSFER_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_MARKET_TRANSFER_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用补贴转账查询接口失败", e);
        }

        return "";
    }

    // 补贴支付（给商户分补贴）
    public static String tradeMarketTransferPayApi(HfTradeMarketPay hfTradeMarketPay) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfTradeMarketPay.getReqSeqId());
        dataMap.put("req_date", hfTradeMarketPay.getReqDate());
        // 出款方商户号
        dataMap.put("out_huifu_id", hfTradeMarketPay.getOutHfId());
        // 出款方子账户号  可指定账户号，仅支持基本户、现金户，不填默认为基本户
//        dataMap.put("out_acct_id", "");
        // 入款方商户号
        dataMap.put("in_huifu_id", hfTradeMarketPay.getInHfId());
        // 入款方子账户号  可指定账户号，仅支持基本户、现金户，不填默认为基本户
        if (!StringUtils.isBlank(hfTradeMarketPay.getInHfAcctId())) {
            dataMap.put("in_acct_id", hfTradeMarketPay.getInHfAcctId());
        }
        // 补贴金额     单位元，需保留小数点后两位，例如：1.00,最低传入0.01(补贴给品牌商户金额，不包含手续费，服务费)
        dataMap.put("ord_amt", hfTradeMarketPay.getTransAmt());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_MARKET_TRANSFER_PAY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_MARKET_TRANSFER_PAY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_MARKET_TRANSFER_PAY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用补贴转账接口失败", e);
        }

        return "";
    }

    // 余额支付查询
    public static String tradeAccountAmtQueryApi(HfTradeAccountPay hfTradeAccountPay) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfTradeAccountPay.getReqSeqId());
        dataMap.put("req_date", hfTradeAccountPay.getReqDate());
        // 发起方商户号
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        // 原交易请求日期
        dataMap.put("org_req_date", hfTradeAccountPay.getOrgReqDate());
        // 原交易请求流水号
        dataMap.put("org_req_seq_id", hfTradeAccountPay.getOrgReqSeqId());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_ACCOUNT_AMT_PAY_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_ACCOUNT_AMT_PAY_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_ACCOUNT_AMT_PAY_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用余额支付查询接口失败", e);
        }

        return "";
    }

    // 余额支付（给商户分本金/给经纪人分佣）
    public static String tradeAccountAmtPayApi(HfTradeAccountPay hfTradeAccountPay) {
        String goodsDesc = hfTradeAccountPay.getGoodsDesc();
        if (StringUtils.isBlank(goodsDesc)) {
            goodsDesc = "活动" + hfTradeAccountPay.getReqSeqId();
        } else {
            goodsDesc = goodsDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5\\-.]", "");
        }

        if (goodsDesc.length() > 20) {
            goodsDesc = goodsDesc.substring(0, 20);
        }

        BigDecimal transAmtBig = new BigDecimal(hfTradeAccountPay.getTransAmt());
        if (transAmtBig.compareTo(BigDecimal.ZERO) <= 0) {
            Throw.isBusinessException("金额不能小于等于0");
        }

        String transAmt = new DecimalFormat("0.00").format(new BigDecimal(hfTradeAccountPay.getTransAmt()));

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfTradeAccountPay.getReqSeqId());
        dataMap.put("req_date", hfTradeAccountPay.getReqDate());
        // 出款方商户号
        dataMap.put("out_huifu_id", SYS_MERCHANT_NO);
        // 支付金额		单位元，需保留小数点后两位
        dataMap.put("ord_amt", transAmt);
        // 商品描述
        dataMap.put("goods_desc", goodsDesc);

        // 分账对象
        Map<String, Object> acctSplitBunch = new HashMap<>();
        List<Map<String, Object>> acctInfos = new ArrayList<>();
        Map<String, Object> acctInfo = new HashMap<>();
        // 分账金额
        acctInfo.put("div_amt", transAmt);
        // 被分账方ID
        acctInfo.put("huifu_id", hfTradeAccountPay.getInHfId());
        if (!StringUtils.isBlank(hfTradeAccountPay.getInHfAcctId())) {
            // 被分账方账户号
            acctInfo.put("acct_id", hfTradeAccountPay.getInHfAcctId());
        }
        acctInfos.add(acctInfo);
        acctSplitBunch.put("acct_infos", acctInfos);
        dataMap.put("acct_split_bunch", JSON.toJSONString(acctSplitBunch));

        // 安全信息
        Map<String, Object> riskCheckData = new HashMap<>();

        // 灵活用工标志	Y：灵活用工，N：非灵活用工(默认)；
        String hycFlag = hfTradeAccountPay.getHycFlag();
        if (!StringUtils.isBlank(hycFlag) && "Y".equals(hycFlag)) {
            // 给经纪人支付佣金

            // 转账原因	01：卡券推广类；02：卡券核销类；03：消费；04：工资代发；05：分润；06：灵活用工
            riskCheckData.put("transfer_type", "06");

            // 灵活用工标志	Y：灵活用工，N：非灵活用工(默认)
            dataMap.put("hyc_flag", hycFlag);
            // 代发模式	1：普票，2：专票。
            dataMap.put("salary_modle_type", "2");
            // 落地公司商户号
            dataMap.put("bmember_id", hfTradeAccountPay.getBmemberId());
        } else {
            // 转账原因	01：卡券推广类；02：卡券核销类；03：消费；04：工资代发；05：分润；06：灵活用工
            riskCheckData.put("transfer_type", "05");
        }

        dataMap.put("risk_check_data", JSON.toJSONString(riskCheckData));


        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_ACCOUNT_AMT_PAY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_ACCOUNT_AMT_PAY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_ACCOUNT_AMT_PAY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用余额支付接口失败", e);
        }

        return "";
    }

    // 个人签约状态查询
    public static String agentSignQueryApi(String contractId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 合同编号
        dataMap.put("contract_id", contractId);
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_SIGN_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_SIGN_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_SIGN_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用个人签约查询接口失败", e);
        }
        return "";
    }

    // 个人签约发起
    public static String agentSignCreateApi(HfAgentUserSignCreate hfAgentUserSignCreate) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 汇付客户Id
        dataMap.put("huifu_id", hfAgentUserSignCreate.getHfId());
        // 落地公司机构号
        dataMap.put("minor_agent_id", hfAgentUserSignCreate.getMinorAgentId());
        dataMap.put("req_seq_id", hfAgentUserSignCreate.getReqSeqId());
        dataMap.put("req_date", hfAgentUserSignCreate.getReqDate());
        // 是否发送签约短信 Y:是，N:否，默认否；
        dataMap.put("send_sms_flag", "Y");

        // 签约结果通知地址
        dataMap.put("asyn_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.AGENT_USER_SIGN_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_SIGN_CREATE_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_SIGN_CREATE_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_SIGN_CREATE_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用个人签约发起接口失败", e);
        }
        return "";
    }

    // 商户签约查询
    public static String merchantSignQueryApi() {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 汇付客户Id
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_SIGN_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_SIGN_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_SIGN_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用商户签约查询接口失败", e);
        }
        return "";
    }

    // 用户业务查询
    public static String agentUserQueryApi(String hfId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 汇付客户Id
        dataMap.put("huifu_id", hfId);
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_USER_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_USER_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_USER_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用用户业务入驻查询接口失败", e);
        }
        return "";
    }

    // 用户业务入驻修改
    public static String agentUserModifyApi(HfAgentUserEnterApply hfAgentUserEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 汇付ID
        dataMap.put("huifu_id", hfAgentUserEnterApply.getHfId());
        dataMap.put("req_seq_id", hfAgentUserEnterApply.getReqSeqId());
        dataMap.put("req_date", hfAgentUserEnterApply.getReqDate());
        // 渠道商/商户汇付Id(所有经纪人都跟平台绑定)
        dataMap.put("upper_huifu_id", SYS_MERCHANT_NO);

        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        cardInfo.put("card_type", "1");
        // 卡户名
        cardInfo.put("card_name", hfAgentUserEnterApply.getCardName());
        // 卡号
        cardInfo.put("card_no", hfAgentUserEnterApply.getCardNo());
        // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
        cardInfo.put("cert_type", "00");
        // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
        cardInfo.put("cert_no", hfAgentUserEnterApply.getCertNo());
        // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
        cardInfo.put("cert_validity_type", String.valueOf(hfAgentUserEnterApply.getCertValidityType()));
        // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
        cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(hfAgentUserEnterApply.getCertValidityType())) {
            // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
            cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertEndDate()));
        }
        // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
        cardInfo.put("mp", hfAgentUserEnterApply.getMobileNo());
        // 银行所在省
        cardInfo.put("prov_id", hfAgentUserEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfAgentUserEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 开通状态	0:关闭 1:开通；
        cashConfig.put("switch_state", "1");
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
        cashConfig.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.00");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 灵活用工开关	N：否（默认） Y：是；
        // 结算卡(手机号,证件号,证件类型)不能为空    证件类型必须为身份证类型, 结算类型不能为对公，    结算账户名需与个人用户姓名一致
//        dataMap.put("open_tax_flag", "Y");

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.AGENT_USER_ENTER_MODIFY_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_USER_MODIFY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_USER_MODIFY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_USER_MODIFY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用用户业务入驻修改接口失败", e);
        }
        return "";
    }

    // 用户业务入驻
    public static String agentUserOpenApi(HfAgentUserEnterApply hfAgentUserEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 汇付ID
        dataMap.put("huifu_id", hfAgentUserEnterApply.getHfId());
        dataMap.put("req_seq_id", hfAgentUserEnterApply.getReqSeqId());
        dataMap.put("req_date", hfAgentUserEnterApply.getReqDate());
        // 渠道商/商户汇付Id(所有经纪人都跟平台绑定)
        dataMap.put("upper_huifu_id", SYS_MERCHANT_NO);

        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        cardInfo.put("card_type", "1");
        // 卡户名
        cardInfo.put("card_name", hfAgentUserEnterApply.getCardName());
        // 卡号
        cardInfo.put("card_no", hfAgentUserEnterApply.getCardNo());
        // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
        cardInfo.put("cert_type", "00");
        // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
        cardInfo.put("cert_no", hfAgentUserEnterApply.getCertNo());
        // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
        cardInfo.put("cert_validity_type", String.valueOf(hfAgentUserEnterApply.getCertValidityType()));
        // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
        cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(hfAgentUserEnterApply.getCertValidityType())) {
            // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
            cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertEndDate()));
        }
        // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
        cardInfo.put("mp", hfAgentUserEnterApply.getMobileNo());
        // 银行所在省
        cardInfo.put("prov_id", hfAgentUserEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfAgentUserEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
        cashConfig.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.00");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 灵活用工开关	N：否（默认） Y：是；
        // 结算卡(手机号,证件号,证件类型)不能为空    证件类型必须为身份证类型, 结算类型不能为对公，    结算账户名需与个人用户姓名一致
        dataMap.put("open_tax_flag", "Y");

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.AGENT_USER_ENTER_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_USER_OPEN_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_USER_OPEN_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_USER_OPEN_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用用户业务入驻接口失败", e);
        }
        return "";
    }

    // 个人用户开户
    public static String agentUserInviteApi(HfAgentUserEnterApply hfAgentUserEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfAgentUserEnterApply.getReqSeqId());
        dataMap.put("req_date", hfAgentUserEnterApply.getReqDate());
        // 个人姓名
        dataMap.put("name", hfAgentUserEnterApply.getPersonName());
        // 个人证件类型   00-身份证
        dataMap.put("cert_type", "00");
        // 个人证件号码
        dataMap.put("cert_no", hfAgentUserEnterApply.getCertNo());
        // 个人证件有效期类型		    1:长期有效 0:非长期有效；
        dataMap.put("cert_validity_type", String.valueOf(hfAgentUserEnterApply.getCertValidityType()));
        // 个人证件有效期开始日期		    日期格式：yyyyMMdd
        dataMap.put("cert_begin_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(hfAgentUserEnterApply.getCertValidityType())) {
            // 个人证件有效期截止日期		日期格式：yyyyMMdd
            dataMap.put("cert_end_date", LocalDateUtil.stringToString(hfAgentUserEnterApply.getCertEndDate()));
        }
        // 手机号
        dataMap.put("mobile_no", hfAgentUserEnterApply.getMobileNo());
        // 是否发送短信标识	Y:发送短信通知，N：不发送短信通知。默认不发送短信通知。
        dataMap.put("sms_send_flag", "N");

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("AGENT_USER_INVITE_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(AGENT_USER_INVITE_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("AGENT_USER_INVITE_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用个人用户开户接口失败", e);
        }
        return "";
    }

    public static String bankPayQueryApi(HfTradeQuery hfTradeQuery) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 商户号
        dataMap.put("huifu_id", hfTradeQuery.getHfMerchantNo());
        // 原交易请求日期
        dataMap.put("org_req_date", hfTradeQuery.getOrgReqDate());
        // 原交易请求流水号
        dataMap.put("org_req_seq_id", hfTradeQuery.getOrgReqSeqId());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("BANK_PAY_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(BANK_PAY_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("BANK_PAY_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用线上交易查询接口失败", e);
        }

        return "";
    }

    // 网银支付
    public static String bankPayApi(HfBankPay hfBankPay) {
        BigDecimal transAmtBig = new BigDecimal(hfBankPay.getTransAmt());
        if (transAmtBig.compareTo(BigDecimal.ZERO) <= 0) {
            Throw.isBusinessException("金额不能小于等于0");
        }

        String transAmt = new DecimalFormat("0.00").format(transAmtBig);

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBankPay.getReqSeqId());
        dataMap.put("req_date", hfBankPay.getReqDate());

        String huifuId = hfBankPay.getHuifuId();
        if (StringUtils.isBlank(huifuId)) {
            // 商户号
            huifuId = SYS_MERCHANT_NO;
            dataMap.put("acct_id", SYS_RECHARGE_ACCOUNT_NO);
        }

        // 商户号
        dataMap.put("huifu_id", huifuId);

        // 订单金额	单位元，需保留小数点后两位
        dataMap.put("trans_amt", transAmt);
        // 订单类型	P：支付，R：充值
        dataMap.put("order_type", "P");
        // 付款方银行编号	若填入付款方银行编号时，同步返回具体银行页面；若未填入付款方银行编号时，同步返回银行选择页面
//        dataMap.put("bank_id", "");
        // 卡类型	D：借记卡（默认），C：信用卡；
        dataMap.put("card_type", "D");
        // 商品描述
        dataMap.put("goods_desc", hfBankPay.getGoodsDesc());
        // 备注		原样返回；
        dataMap.put("remark", hfBankPay.getRemark());
        // 订单失效时间	格式yyyyMMddHHmmss；（注：工商银行需传90min以上方能成功）；不传默认5小时；
        dataMap.put("time_expire", hfBankPay.getTimeExpire());
        // 网关支付类型	01: 个人网关，02: 企业网关，不传值，默认：01（个人网关）；
        dataMap.put("gate_type", "02");

        // 网联扩展数据
        Map<String, Object> extendPayData = new HashMap<>();
        // 商品简称
        extendPayData.put("goods_short_name", hfBankPay.getGoodsDesc());
        // 网关支付受理渠道	01：电脑浏览器，02：手机浏览器，03：手机应用程序，99：其他；
        extendPayData.put("gw_chnnl_tp", "01");
        // 业务种类	B2C默认取值100099，B2B默认取值200000    130001-银行/支付账户服务/支付账户充值
        extendPayData.put("biz_tp", "130001");
        dataMap.put("extend_pay_data", JSON.toJSONString(extendPayData));

        Map<String, Object> terminalDeviceData = new HashMap<>();
        // 交易设备类型   1：手机, 2：平板, 3：手表, 4：PC
        terminalDeviceData.put("device_type", "4");
        // 交易设备IP	    用于标识交易设备IP地址，绑卡设备所在的公网IP，可用于定位所属地区，不是wifi连接时的局域网IP。
        terminalDeviceData.put("device_ip", hfBankPay.getRequestIp());
        dataMap.put("terminal_device_data", JSON.toJSONString(terminalDeviceData));

        // 安全信息
        Map<String, Object> riskCheckData = new HashMap<>();
        // IP地址、经纬度、基站地址最少要送其中一项；
        riskCheckData.put("ip_addr", hfBankPay.getRequestIp());
        dataMap.put("risk_check_data", JSON.toJSONString(riskCheckData));

        // 异步通知地址	交易结果异步通知地址，格式以http或https开头。
        dataMap.put("notify_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.BANK_PAY_NOTIFY_URL);
        // 页面跳转地址	页面跳转地址，跳转至商户前端地址；
//        dataMap.put("front_url", "");

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("BANK_PAY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(BANK_PAY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("BANK_PAY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用网银支付接口失败", e);
        }

        return "";
    }

    // 交易退款查询
    public static String tradeRefundQueryApi(HfTradeRefundQuery hfTradeRefundQuery) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        // 商户号
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        // 退款请求日期		    格式：yyyyMMdd；
        dataMap.put("org_req_date", hfTradeRefundQuery.getOrgReqDate());
        // 退款全局流水号		退款请求流水号,退款全局流水号,终端订单号三选一不能都为空；
//        dataMap.put("org_hf_seq_id", "");
        // 终端订单号	    退款请求流水号,退款全局流水号,终端订单号三选一不能都为空；
//        dataMap.put("mer_ord_id", "");
        // 退款请求流水号	    退款请求流水号,退款全局流水号,终端订单号三选一不能都为空；
        dataMap.put("org_req_seq_id", hfTradeRefundQuery.getOrgReqSeqId());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_REFUND_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_REFUND_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_REFUND_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用交易退款查询接口失败", e);
        }

        return "";
    }

    // 交易退款
    public static String tradeRefundApi(HfTradeRefund hfTradeRefund) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfTradeRefund.getReqSeqId());
        dataMap.put("req_date", hfTradeRefund.getReqDate());
        // 商户号
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        // 申请退款金额	单位元，需保留小数点后两位；
        dataMap.put("ord_amt", hfTradeRefund.getRefundAmt().toString());
        // 原交易请求日期	    格式：yyyyMMdd；
        dataMap.put("org_req_date", hfTradeRefund.getOrgReqDate());
        // 原交易全局流水号	org_hf_seq_id，org_party_order_id，org_req_seq_id三选一；
//        dataMap.put("org_hf_seq_id", "");
        // 原交易微信支付宝的商户单号	  org_hf_seq_id，org_party_order_id，org_req_seq_id三选一；
//        dataMap.put("org_party_order_id", "");
        // 原交易请求流水号		   org_hf_seq_id，org_party_order_id，org_req_seq_id三选一；
        dataMap.put("org_req_seq_id", hfTradeRefund.getOrgReqSeqId());
        // 异步通知地址
        dataMap.put("notify_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.TRADE_REFUND_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_REFUND_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_REFUND_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_REFUND_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用交易退款接口失败", e);
        }

        return "";
    }

    // 交易查询
    public static String tradeQueryApi(HfTradeQuery hfTradeQuery) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 商户号
        dataMap.put("huifu_id", SYS_MERCHANT_NO);
        // 原机构请求日期
        dataMap.put("org_req_date", hfTradeQuery.getOrgReqDate());
        // 汇付服务订单号      out_ord_id,org_hf_seq_id,org_req_seq_id 必填其一
//        dataMap.put("out_ord_id", "");
        // 创建服务订单返回的汇付全局流水号     out_ord_id,org_hf_seq_id,org_req_seq_id 必填其一
//        dataMap.put("org_hf_seq_id", "");
        // 服务订单创建请求流水号	    out_ord_id,org_hf_seq_id,org_req_seq_id 必填其一
        dataMap.put("org_req_seq_id", hfTradeQuery.getOrgReqSeqId());

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("TRADE_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(TRADE_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("TRADE_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用交易查询接口失败", e);
        }

        return "";
    }

    // 微信小程序预下单
    public static String preOrderApi(HfJsPay hfJsPay) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfJsPay.getReqSeqId());
        dataMap.put("req_date", hfJsPay.getReqDate());
        // 预下单类型	    微信预下单：3；
        dataMap.put("pre_order_type", "3");
        // 商户号
        dataMap.put("huifu_id", hfJsPay.getHfMerchantNo());
        // 商品描述
        dataMap.put("goods_desc", hfJsPay.getGoodsDesc());
        // 交易类型：T_JSAPI: 微信公众号  T_MINIAPP: 微信小程序    A_JSAPI: 支付宝JS  A_NATIVE: 支付宝正扫 U_NATIVE: 银联正扫
        //          U_JSAPI: 银联JS   D_NATIVE: 数字人民币正扫   T_H5：微信直连H5支付     T_APP：微信APP支付（只支持直连）  T_NATIVE：微信正扫（只支持直连）
        dataMap.put("trade_type", "T_MINIAPP");
        // 交易金额	单位元，需保留小数点后两位
        dataMap.put("trans_amt", hfJsPay.getTransAmt());
        // 交易失效时间	请求格式：yyyyMMddHHmmss；    注意:为空默认失效时间为5分钟
        dataMap.put("time_expire", hfJsPay.getTimeExpire());

        Map<String, Object> miniappData = new HashMap<>();
        // 是否生成scheme_code  Y；适用于APP、短信链接、邮件、外部网页、微信内等拉起汇付小程序的业务场景时需填Y；N；通过汇付微信插件支付填N
        miniappData.put("need_scheme", "N");
        dataMap.put("miniapp_data", JSON.toJSONString(miniappData));

        // 异步通知地址
        dataMap.put("notify_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.PRE_ORDER_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("PRE_ORDER_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(PRE_ORDER_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("PRE_ORDER_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用微信小程序预下单接口失败", e);
        }

        return "";
    }

    // 聚合正扫
    public static String jsPayApi(HfJsPay hfJsPay) {
        String goodsDesc = hfJsPay.getGoodsDesc();
        if (StringUtils.isBlank(goodsDesc)) {
            goodsDesc = "活动" + hfJsPay.getReqSeqId();
        } else {
            goodsDesc = goodsDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5\\-.]", "");
        }

        if (goodsDesc.length() > 20) {
            goodsDesc = goodsDesc.substring(0, 20);
        }

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfJsPay.getReqSeqId());
        dataMap.put("req_date", hfJsPay.getReqDate());
        // 商户号
        dataMap.put("huifu_id", SYS_MERCHANT_NO);

        String attach = hfJsPay.getAttach();
        if (!StringUtils.isBlank(attach)) {
            // 会员套餐、次卡费，收款账户是平台的充值户，消费者下单，收款账户是平台的基本户
            // 不填默认为基本户
            if (PayAttachEnum.MEMBER_FEE_PAY.getName().equals(attach) || PayAttachEnum.MEMBER_CARD_PAY.getName().equals(attach)) {
                dataMap.put("acct_id", SYS_RECHARGE_ACCOUNT_NO);
            }
        }

        // 商品描述
        dataMap.put("goods_desc", goodsDesc);
        // 交易类型：T_JSAPI: 微信公众号  T_MINIAPP: 微信小程序    A_JSAPI: 支付宝JS  A_NATIVE: 支付宝正扫 U_NATIVE: 银联正扫
        //          U_JSAPI: 银联JS   D_NATIVE: 数字人民币正扫   T_H5：微信直连H5支付     T_APP：微信APP支付（只支持直连）  T_NATIVE：微信正扫（只支持直连）
        dataMap.put("trade_type", "T_MINIAPP");
        // 交易金额	单位元，需保留小数点后两位
        dataMap.put("trans_amt", hfJsPay.getTransAmt());
        // 交易有效期	请求格式：yyyyMMddHHmmss；
        dataMap.put("time_expire", hfJsPay.getTimeExpire());

        // 聚合正扫微信拓展参数集合
        Map<String, Object> wxData = new HashMap<>();
        // 子商户公众账号id	微信分配的子商户公众账号id，微信js/小程序支付必传。
        wxData.put("sub_appid", wxConfig.appId);
        // 子商户用户标识	微信js/小程序支付必传
        wxData.put("sub_openid", hfJsPay.getWxOpenid());
        // 附加数据	在查询api和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据；
        wxData.put("attach", hfJsPay.getAttach());
        dataMap.put("wx_data", JSON.toJSONString(wxData));

        // 异步通知地址
        dataMap.put("notify_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.JS_PAY_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("JS_PAY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(JS_PAY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("JS_PAY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用聚合正扫支付接口失败", e);
        }

        return "";
    }

    // 商户详细信息查询（查询合同签约状态）
    public static String merchantBasicDataQueryApi(String hfMerchantNo) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 商户号
        dataMap.put("huifu_id", hfMerchantNo);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_BASIC_DATA_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_BASIC_DATA_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_BASIC_DATA_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用商户详细信息查询（查询合同签约状态）接口失败", e);
        }

        return "";
    }

    // 微信实名认证状态查询
    public static String wxBusinessRealQueryApi(String hfMerchantNo) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 商户号
        dataMap.put("huifu_id", hfMerchantNo);
        // 子渠道号 微信渠道号 00008374(汇付天下)
        dataMap.put("pay_channel_id", "00008374");
        // 支付场景   02
        dataMap.put("pay_scene", "02");

        // 异步通知地址
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.WX_BUSINESS_CONFIG_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("WX_BUSINESS_REAL_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(WX_BUSINESS_REAL_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("WX_BUSINESS_REAL_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用微信实名认证状态查询接口失败", e);
        }

        return "";
    }

    // 微信商户配置
    public static String wxBusinessConfigApi(String hfMerchantNo) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 商户号
        dataMap.put("huifu_id", hfMerchantNo);
        // 业务开通类型   02
        dataMap.put("fee_type", "02");
        // 公众号支付Appid
//        dataMap.put("wx_woa_app_id", "");
        // 微信公众号授权目录
//        dataMap.put("wx_woa_path", "");
        // 微信公众号APPID对应的秘钥
//        dataMap.put("wx_woa_secret", "");
        // 微信小程序APPID
        dataMap.put("wx_applet_app_id", wxConfig.appId);
        // 微信小程序APPID对应的秘钥
        dataMap.put("wx_applet_secret", wxConfig.appSecret);
        // 微信渠道号 00008374(汇付天下)
        dataMap.put("bank_channel_no", "00008374");

        // 异步通知地址
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.WX_BUSINESS_CONFIG_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("WX_BUSINESS_CONFIG_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(WX_BUSINESS_CONFIG_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("WX_BUSINESS_CONFIG_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用微信商户配置接口失败", e);
        }

        return "";
    }

    // 申请单查询
    public static String basicDataQueryApi(String applyNo, String huiFuId) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        dataMap.put("req_date", yyyyMMdd);
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("apply_no", applyNo);
        dataMap.put("huifu_id", huiFuId);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("BASIC_STATUS_QUERY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(BASIC_STATUS_QUERY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("BASIC_STATUS_QUERY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用申请单查询接口失败", e);
        }

        return "";
    }

    // 个人商户基本信息入驻
    public static String merchantEnterIndvApi(HfBusinessEnterApply hfBusinessEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 商户名称，必须与商家营业执照上的名称一致；个体工商户的营业执照如没有名称、名称为“*”或空，则商户名称应填 “个体户XXX”（XXX为营业执照上经营者姓名），如“个体户张三”，汉字以2个字符计算
        dataMap.put("reg_name", hfBusinessEnterApply.getBusinessName());
        // 商户简称，需与商户注册名称相关
        dataMap.put("short_name", hfBusinessEnterApply.getBusinessShortName());
        // 小票名称
        dataMap.put("receipt_name", hfBusinessEnterApply.getBusinessName());
        // 公司类型 1：政府机构,2：国营企业,3：私营企业,4：外资企业,5：个体工商户,6：其它组织,7：事业单位
//        dataMap.put("ent_type", hfBusinessEnterApply.getCompanyType());
        dataMap.put("mcc", hfBusinessEnterApply.getMcc());
        // 场景类型	ONLINE：线上场景，OFFLINE：线下场景，ALL：线上线下；
        dataMap.put("scene_type", "ALL");
        // 经营省
        dataMap.put("prov_id", hfBusinessEnterApply.getBusinessProvinceCode());
        // 经营市
        dataMap.put("area_id", hfBusinessEnterApply.getBusinessCityCode());
        // 经营区
        dataMap.put("district_id", hfBusinessEnterApply.getBusinessCountyCode());
        // 经营详细地址
        String businessAddress = hfBusinessEnterApply.getBusinessAddress();
        if (!StringUtils.isBlank(businessAddress)) {
            businessAddress = businessAddress.replaceAll(" ", "").replaceAll("[\\t\\n\\r]", "");
            dataMap.put("detail_addr", businessAddress);
        }
        // 法人证件号码
        dataMap.put("legal_cert_no", hfBusinessEnterApply.getLegalCertNo());

        Integer legalCertValidityType = hfBusinessEnterApply.getLegalCertValidityType();
        // 法人证件有效期类型
        dataMap.put("legal_cert_validity_type", legalCertValidityType);
        // 法人证件有效期开始日期	日期格式：yyyyMMdd
        dataMap.put("legal_cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(legalCertValidityType)) {
            // 法人证件有效期截止日期	日期格式：yyyyMMdd
            dataMap.put("legal_cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertEndDate()));
        }

        // 法人身份证地址
        String legalAddr = hfBusinessEnterApply.getLegalAddr();
        if (!StringUtils.isBlank(legalAddr)) {
            legalAddr = legalAddr.replaceAll(" ", "").replaceAll("[\\t\\n\\r]", "");
            dataMap.put("legal_addr", legalAddr);
        }
        // 法人身份证国徽面	企业商户填写。文件类型：F03
        dataMap.put("legal_cert_back_pic", hfBusinessEnterApply.getLegalCertBackPic());
        // 法人身份证人像面	企业商户填写。文件类型：F02
        dataMap.put("legal_cert_front_pic", hfBusinessEnterApply.getLegalCertFrontPic());
        // 联系人姓名
        dataMap.put("contact_name", hfBusinessEnterApply.getContactName());
        // 联系人手机号
        dataMap.put("contact_mobile_no", hfBusinessEnterApply.getContactMobileNo());
        // 联系人电子邮箱
        dataMap.put("contact_email", hfBusinessEnterApply.getContactEmail());

        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户名，结算银行卡对应的户名；
        cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
        // 结算账号	结算银行卡号，不支持贷记卡。为避免资金结算失败，请正确填写；
        cardInfo.put("card_no", hfBusinessEnterApply.getCardNo());
        // 银行所在省
        cardInfo.put("prov_id", hfBusinessEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfBusinessEnterApply.getBankCityCode());
        // 银行编号
        cardInfo.put("bank_code", hfBusinessEnterApply.getBankCode());
        // 持卡人证件类型
        cardInfo.put("cert_type", hfBusinessEnterApply.getCertType());
        // 持卡人证件号码 年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
        cardInfo.put("cert_no", hfBusinessEnterApply.getCertNo());
        // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
        cardInfo.put("cert_validity_type", String.valueOf(hfBusinessEnterApply.getCertValidityType()));
        // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
        cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(hfBusinessEnterApply.getCertValidityType())) {
            // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
            cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertEndDate()));
        }
        // 结算人手机号		11位数字
        cardInfo.put("mp", hfBusinessEnterApply.getMp());
        // 结算卡正面	对私结算必填。文件类型：F13
        dataMap.put("settle_card_front_pic", hfBusinessEnterApply.getSettleCardFrontPic());

        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 结算规则配置
//        Map<String, String> settle_config = new HashMap<>();
//        // 结算周期	D1：下个自然日到账， T1：下个工作日到账
//        settle_config.put("settle_cycle", "T1");
//        // 手续费外扣标记	1:外扣，结算时从out_settle_huifuid账户扣手续费   2:内扣，从结算金额中扣手续费，默认为内扣
//        settle_config.put("out_settle_flag", "2");
//        // 结算方式	P0：批次结算 ，P1：定时结算 批次结算指按照指定结算批次号进行资金结算，自定义时间结算是指按照商户指定到账时间进行资金结算。两种结算方式需二选一，不填默认P0：批次结算
//        settle_config.put("settle_pattern", "P0");
//        // 结算批次号	结算方式为P0：批次结算时必填，即将按指定结算批次号进行资金结算；示例值：100
//        // 0：0点昨日余额结算批次，非优先到账批则预计到账时间10:30
//        // 100：1点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 200：2点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 300：3点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 400：4点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 500：5点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30  600：6点余额结算批次，预计到账时间10:30
//        // 700：7点余额结算批次，预计到账时间10:30  800：8点余额结算批次，预计到账时间10:30
//        // 900：9点余额结算批次，预计到账时间10:30  1000：10点余额结算批次，预计到账时间14:00
//        // 1100：11点余额结算批次，预计到账时间14:00  1200：12点余额结算批次，预计到账时间14:00
//        settle_config.put("settle_batch_no", "100");
//        // 是否优先到账	当settle_pattern=P0时选填，不填默认为N，该值在结算那批次号[0-500]间生效   Y：是，N：否
//        settle_config.put("is_priority_receipt", "N");
//        dataMap.put("settle_config", settle_config);

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
        cashConfig.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.50");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 商户ICP备案编号或网站许可证号；类型为PC网站时，且为企业商户，且开通快捷或网银，或大额转账，或余额支付或分账业务（20%（不含）-100%），或为个人商户开通分账业务（10%（不含）-100%），必填
        // 商家入驻必填，商户入驻不需要
        dataMap.put("mer_icp", "闽ICP备2023027415号-1X");
        // 线下经营-门头照	    文件类型：F22；
        dataMap.put("store_header_pic", hfBusinessEnterApply.getStoreHeaderPic());
        // 线下经营-内景照	    文件类型：F24；
        dataMap.put("store_indoor_pic", hfBusinessEnterApply.getStoreIndoorPic());
        // 线下经营-收银台	    文件类型：F105；
        dataMap.put("store_cashier_desk_pic", hfBusinessEnterApply.getStoreCashierDeskPic());

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_ENT_INDV_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_INDV_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_INDV_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_INDV_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用个人商户基本信息入驻接口失败", e);
        }
        return "";
    }

    // 商户业务开通
    public static String merchantOpenApi(HfBusinessEnterApply hfBusinessEnterApply) {
        String hfMerchantNo = hfBusinessEnterApply.getHfMerchantNo();

        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 汇付客户Id
        dataMap.put("huifu_id", hfMerchantNo);
        // 微信支付宝商户简称	企业商户必填，需与商户注册名称全称相关；用于微信、支付宝入驻时上传；
        dataMap.put("short_name", hfBusinessEnterApply.getBusinessShortName());

        // 协议信息实体
        Map<String, Object> agreementInfo = new HashMap<>();
        // 协议类型	0-电子协议 1-纸质协议 3-挂网协议
        agreementInfo.put("agreement_type", "0");
        dataMap.put("agreement_info", JSON.toJSONString(agreementInfo));

        // 	签约人
        Map<String, Object> signUserInfo = new HashMap<>();
        // 签约人类型：1-法人，2-联系人
        Integer signUserType = hfBusinessEnterApply.getSignUserType();
        if (SignUserTypeEnum.LEGAL.getValue().equals(signUserType)) {
            // 签约人类型	 LEGAL-法人，对公结算或对私法人结算时可选法人签约；CONTACT-联系人，对公结算可选联系人（经办人）签约；OTHER-其他，对私非法人结算选“其他”，必须是结算人；
            signUserInfo.put("type", SignUserTypeEnum.LEGAL.getName());
            // 手机号	签约人类型=法人/其他 ，必填
            signUserInfo.put("mobile_no", hfBusinessEnterApply.getLegalMobileNo());
        } else {
            // 签约人类型	 LEGAL-法人，对公结算或对私法人结算时可选法人签约；CONTACT-联系人，对公结算可选联系人（经办人）签约；OTHER-其他，对私非法人结算选“其他”，必须是结算人；
            signUserInfo.put("type", SignUserTypeEnum.CONTACT.getName());
            // 身份证  签约人类型=联系人/其他，必填
            signUserInfo.put("cert_no", hfBusinessEnterApply.getContactCertNo());
        }
        dataMap.put("sign_user_info", JSON.toJSONString(signUserInfo));

        // 是否开通网银	Y:是 N:否
        dataMap.put("online_flag", "Y");
        // 商户业务类型   01:综合电商-电商平台
        dataMap.put("mer_bus_type", "01");

        // 线上费率配置
        List<Map<String, Object>> onlineFeeConfList = new ArrayList<>();
        List<String> bankCodeList = Arrays.asList(
                "01040000", // 中国银行
                "01030000", // 中国农业银行
                "01020000", // 中国工商银行
                "01050000", // 中国建设银行
                "03010000", // 交通银行
                "04030000", // 中国邮政储蓄银行
                "03080000", // 招商银行
                "03100000", // 上海浦东发展银行
                "03060000", // 广发银行
                "03050000", // 中国民生银行
                "03090000", // 兴业银行
                "03020000" // 中信银行
        );
        for (String bankId : bankCodeList) {
            Map<String, Object> onlineFeeConfMap = new HashMap<>(5);
            // 业务类型	ONLINE_PERSON:个人网银支付    ONLINE_ENT:企业网银支付
            onlineFeeConfMap.put("fee_type", "ONLINE_ENT");
            // 银行编码	01040000-中国银行	    01030000-中国农业银行	    01020000-中国工商银行	    01050000-中国建设银行
            //          03010000-交通银行	    04030000-中国邮政储蓄银行	    03040000-华夏银行	    03080000-招商银行
            //          03100000-上海浦东发展银行	    03160000-浙商银行	    03060000-广发银行	    03130012-天津银行
            //          31346100-济宁银行	            03050000-中国民生银行
            onlineFeeConfMap.put("bank_id", bankId);
            // 功能开关状态	各银行不同支付方式的开关状态；1开，0关；
            onlineFeeConfMap.put("stat_flag", "1");
            // 借贷标志	D:借记,C:贷记；B2B网银填写D；
            onlineFeeConfMap.put("dc_flag", "D");
            // 手续费（固定/元）
            onlineFeeConfMap.put("fix_amt", "12.00");
            // 单笔限额	快捷不论借贷只取大的值；网银不论对公对私只取大的值；
            onlineFeeConfMap.put("pay_every_deal", "100000.00");
            // 单日限额	快捷不论借贷只取大的值；网银不论对公对私只取大的值；
            onlineFeeConfMap.put("pay_everyday", "200000.00");
            onlineFeeConfList.add(onlineFeeConfMap);
        }
        dataMap.put("online_fee_conf_list", JSON.toJSONString(onlineFeeConfList));

        // 线上业务类型编码     电商平台        《增值电信业务经营许可证》       F301(文件类型)
        dataMap.put("online_busi_type", "H5311L");

        // 运营媒介	基本信息入驻接口中scene_type=ONLINE/ALL时必填；  如果开通快捷、网银、余额支付、分账、银行大额转账需提供运营媒介材料
        List<Map<String, Object>> onlineMediaInfoList = new ArrayList<>();
        Map<String, Object> onlineMediaInfoMap = new HashMap<>();
        // 运营媒介类型	S3-小程序场景；若媒介项为小程序：必填字段（小程序名称、测试账号、密码）
        onlineMediaInfoMap.put("media_type", "S3");
        // 媒介名称	PC网站域名／APP名称／小程序名称／公众号名称；
        onlineMediaInfoMap.put("media_name", "火动通告");
        // 测试账号
        onlineMediaInfoMap.put("test_account", "test");
        // 测试密码
        onlineMediaInfoMap.put("test_secret", "test");
        // 运营媒介-首页
        onlineMediaInfoMap.put("media_front_page", "9a5c8ba4-cc7e-3e65-874d-329140aaa782");
        // 运营媒介-服务/商品明细页面
        onlineMediaInfoMap.put("media_service_page", "381625a6-bd06-3a4f-8b79-b7e5fb2f4c05");
        // 运营媒介-下单场景页面
        onlineMediaInfoMap.put("media_order_page", "cb848884-0a6c-3be6-b531-bc2b00b95d96");
        // 运营媒介-支付页面
        onlineMediaInfoMap.put("media_pay_page", "cb1ba532-fa1a-3236-a6ca-ffcf1e432447");
        // 媒介主体与商户主体是否一致    若不一致，则需提供ICP备案/APP/微信公众号/小程序主体与商户的使用授权或开发证明材料；
        onlineMediaInfoMap.put("media_mer_common_flag", "N");
        // 授权或开发证明材料
        onlineMediaInfoMap.put("authorize_materials", "e1c4ad4a-07ff-3f28-80d2-0d2cf934e70e");
        onlineMediaInfoList.add(onlineMediaInfoMap);
        dataMap.put("online_media_info_list", JSON.toJSONString(onlineMediaInfoList));

        // 补充文件信息   据开通的功能补充相关材料，包括商户纸质协议说明、线上行业补充材料、开通余额支付补充材料
        List<Map<String, Object>> extendedMaterialList = new ArrayList<>();

        // 增值电信业务经营许可证（开通网银需要）
        Map<String, Object> extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "9144b65d-ca0b-3d8a-9721-b68653fe0f08");
        extendedMaterialMap.put("file_type", "F301");
        extendedMaterialList.add(extendedMaterialMap);

        // 协议-供应商协议（开通网银需要）
        extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "b5e41bf4-43b1-3906-adef-8d38699a58d7");
        extendedMaterialMap.put("file_type", "F353");
        extendedMaterialList.add(extendedMaterialMap);

        // 凭证-发货记录/物流凭证（开通网银需要）
        extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "0ca0bc39-f218-38eb-8411-d70f2e6a1286");
        extendedMaterialMap.put("file_type", "F364");
        extendedMaterialList.add(extendedMaterialMap);

        // 协议-平台用户开户协议（开通网银需要）
        extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "a9ab3fe8-457f-3ff5-90fa-b16c6adc4010");
        extendedMaterialMap.put("file_type", "F346");
        extendedMaterialList.add(extendedMaterialMap);

        // 交易双方历史合作项目流水证明（开通余额支付需要）
        extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "ac465cf6-56fd-393d-b12d-4515fbc9a85f");
        extendedMaterialMap.put("file_type", "F447");
        extendedMaterialList.add(extendedMaterialMap);

        // 其他交易双方合作协议（开通余额支付需要）
        extendedMaterialMap = new HashMap<>();
        extendedMaterialMap.put("file_id", "0316eab9-b4e3-3295-8315-bc586582c74e");
        extendedMaterialMap.put("file_type", "F453");
        extendedMaterialList.add(extendedMaterialMap);
        dataMap.put("extended_material_list", JSON.toJSONString(extendedMaterialList));

        // 微信配置对象
//        List<Map<String, Object>> wxConfigs = new ArrayList<>();
//        Map<String, Object> wxConfListMap = new HashMap<>();
//        // 支付场景	1：线下反扫  2：线下公众号 3：线下小程序 4：线上公众号
//        // 5：线上小程序   6：教培行业  7：校园餐饮（需要调商户活动报名接口）8：教育K12
//        // 9：非在线教培（需要调商户活动报名接口）  10：非盈利费率    11：保险费率     12：线上反扫
//        wxConfListMap.put("pay_scene", "3");
//        // 个体工商户、小微商户必填；微信暂不支持修改；
//        wxConfListMap.put("mcc", hfBusinessEnterApply.getMcc());
//        // 手续费（%）	数字类型，大于等于0,保留2位小数；
//        wxConfListMap.put("fee_rate", "0.5");
//        // 最低收取手续费（元）	    固定金额保留2位小数；大于0。需要渠道商开通此功能。
//        wxConfListMap.put("fee_min_amt", "0.01");
//
//        // 是否需要实名认证	Y-是，业务功能开通成功后使用法人信息发起实名认证申请 ； N-否；默认为N ;
//        wxConfListMap.put("is_check_real_name", "Y");
//        Map<String, Object> wxRealNameInfoMap = new HashMap<>();
//        // 证书类型	    CERTIFICATE_TYPE_2389：统一社会信用代码证书
//        wxRealNameInfoMap.put("cert_type", "CERTIFICATE_TYPE_2389");
//        wxConfListMap.put("wx_real_name_info", JSON.toJSONString(wxRealNameInfoMap));
//
//        wxConfigs.add(wxConfListMap);
//        dataMap.put("wx_conf_list", JSON.toJSONString(wxConfigs));

        // 余额支付配置
        Map<String, Object> balancePayConfig = new HashMap<>();
        // 支付手续费(%)
        balancePayConfig.put("fee_rate", "0");
        // 支付固定手续费(元)
        balancePayConfig.put("fee_fix_amt", "0.00");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        balancePayConfig.put("out_fee_flag", "2");
        // 业务模式	2-入驻商户货款（周期性结算） 3-营销补贴（周期性结算） 4-推广方（渠道/代理/个人）的服务佣金/抽成 5-红包发放 6-钱包功能 7-其他模式
        balancePayConfig.put("balance_model", "7");

        Map<String, Object> descriptionInfo = new HashMap<>();
        // 业务模式说明
        descriptionInfo.put("busi_instruction", BUSINESS_INSTRUCTION);
        // 资金流向说明
        descriptionInfo.put("capital_instruction", CAPITAL_INSTRUCTION);
        // 功能开通用途说明
        descriptionInfo.put("function_instruction", FUNCTION_INSTRUCTION);
        balancePayConfig.put("description_info", JSON.toJSONString(descriptionInfo));
        dataMap.put("balance_pay_config", balancePayConfig);

        // 补贴支付
//        Map<String, Object> combine_pay_config = new HashMap<>();
//        // 支付手续费(%)	支付手续费(%) 支持两位小数 fee_rate与fee_fix_amt 不能同时为空；示例值：0.50代表费率为0.5%
//        combine_pay_config.put("fee_rate", "2");
//        // 是否交易手续费外扣    1:外扣，仅支持外扣
//        combine_pay_config.put("out_fee_flag", "1");
//        // 交易手续费外扣汇付ID	    开通交易手续费外扣时必填
//        combine_pay_config.put("out_fee_huifuid", hfMerchantNo);
//        // 交易手续费外扣时的账户类型	01-基本户（不填默认01），05-充值户，09-营销户
//        combine_pay_config.put("out_fee_acct_type", "09");
//        dataMap.put("combine_pay_config", combine_pay_config);

        // 异步消息接收地址	审核消息接收地址
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_OPEN_AUDIT_NOTIFY_URL);
        // 业务开通结果异步消息接收地址	当前申请同步成功或者审核通过之后
        dataMap.put("busi_async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_OPEN_BUSINESS_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_OPEN_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_OPEN_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_OPEN_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用商户业务开通接口失败", e);
        }
        return "";
    }

    // 修改子账号配置
    public static String merchantSettleModifyApi(HfBusinessEnterApply hfBusinessEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 商户汇付Id
        dataMap.put("huifu_id", hfBusinessEnterApply.getHfMerchantNo());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 子账户号
        dataMap.put("acct_id", hfBusinessEnterApply.getAcctId());
        // 子账户类型	    02:现金户
//        dataMap.put("acct_type", "02");
        // 账户名称
//        dataMap.put("acct_name", "现金账户");

        Integer cardType = hfBusinessEnterApply.getCardType();
        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        cardInfo.put("card_type", String.valueOf(cardType));
        // 结算账户名	当card_type=0时填写企业名称 当card_type=1时填写法人姓名，对私法人结算银行户名与法人姓名必需一致；当card_type=2时填写非法人姓名
        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 企业名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 银行编号	当card_type=0时必填， 当card_type=1或2时非必填
//            card_info.put("bank_code", hfBusinessEnterApply.getBankCode());
            // 联行号	当card_type=0时必填， 当card_type=1或2时非必填
            cardInfo.put("branch_code", hfBusinessEnterApply.getBranchCode());
            // 开户支行名称。 当card_type=0时必填， 当card_type=1或2时非必填；
//            card_info.put("branch_name", hfBusinessEnterApply.getBranchName());
        } else if (CardTypeEnum.DS.getValue().equals(cardType)) {
            // 账户名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
            cardInfo.put("cert_type", hfBusinessEnterApply.getCertType());
            // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
            cardInfo.put("cert_no", hfBusinessEnterApply.getCertNo());
            // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
            cardInfo.put("cert_validity_type", String.valueOf(hfBusinessEnterApply.getCertValidityType()));
            // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
            cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(hfBusinessEnterApply.getCertValidityType())) {
                // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
                cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertEndDate()));
            }
            // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
            cardInfo.put("mp", hfBusinessEnterApply.getMp());
            // 结算卡正面	对私结算必填。文件类型：F13
            dataMap.put("settle_card_front_pic", hfBusinessEnterApply.getSettleCardFrontPic());
            // 结算人身份证国徽面	对私结算必填。文件类型：F56；
            dataMap.put("settle_cert_back_pic", hfBusinessEnterApply.getSettleCertBackPic());
            // 结算人身份证人像面	对私结算必填。文件类型：F55；
            dataMap.put("settle_cert_front_pic", hfBusinessEnterApply.getSettleCertFrontPic());
        }
        // 结算账号	结算银行卡号，为避免资金结算失败，请正确填写；
        cardInfo.put("card_no", hfBusinessEnterApply.getCardNo());
        // 银行所在省
        cardInfo.put("prov_id", hfBusinessEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfBusinessEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 结算规则配置
//        Map<String, String> settle_config = new HashMap<>();
//        // 状态 1:开通 0:关闭
//        settle_config.put("settle_status", "0");
//        // 结算周期	D1：下个自然日到账， T1：下个工作日到账
//        settle_config.put("settle_cycle", "T1");
//        // 手续费外扣标记	1:外扣，结算时从out_settle_huifuid账户扣手续费   2:内扣，从结算金额中扣手续费，默认为内扣
//        settle_config.put("out_settle_flag", "2");
//        // 结算方式	P0：批次结算 ，P1：定时结算 批次结算指按照指定结算批次号进行资金结算，自定义时间结算是指按照商户指定到账时间进行资金结算。两种结算方式需二选一，不填默认P0：批次结算
//        settle_config.put("settle_pattern", "P0");
//        // 结算批次号	结算方式为P0：批次结算时必填，即将按指定结算批次号进行资金结算；示例值：100
//        // 0：0点昨日余额结算批次，非优先到账批则预计到账时间10:30
//        // 100：1点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 200：2点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 300：3点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 400：4点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 500：5点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30  600：6点余额结算批次，预计到账时间10:30
//        // 700：7点余额结算批次，预计到账时间10:30  800：8点余额结算批次，预计到账时间10:30
//        // 900：9点余额结算批次，预计到账时间10:30  1000：10点余额结算批次，预计到账时间14:00
//        // 1100：11点余额结算批次，预计到账时间14:00  1200：12点余额结算批次，预计到账时间14:00
//        settle_config.put("settle_batch_no", "100");
//        // 是否优先到账	当settle_pattern=P0时选填，不填默认为N，该值在结算那批次号[0-500]间生效   Y：是，N：否
//        settle_config.put("is_priority_receipt", "N");
//        dataMap.put("settle_config", settle_config);

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
//        cash_config.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.50");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        // 状态   0:关闭，1:开通
        cashConfig.put("switch_state", "1");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_SETTLE_MODIFY_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_SETTLE_MODIFY_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_SETTLE_MODIFY_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_SETTLE_MODIFY_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用修改子账号配置接口失败", e);
        }
        return "";
    }

    // 子账号开通
    public static String merchantSettleConfigApi(HfBusinessEnterApply hfBusinessEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 商户汇付Id
        dataMap.put("huifu_id", hfBusinessEnterApply.getHfMerchantNo());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 子账户类型	    02:现金户
        dataMap.put("acct_type", "02");
        // 账户名称
        dataMap.put("acct_name", "现金账户");

        Integer cardType = hfBusinessEnterApply.getCardType();
        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        cardInfo.put("card_type", String.valueOf(cardType));
        // 结算账户名	当card_type=0时填写企业名称 当card_type=1时填写法人姓名，对私法人结算银行户名与法人姓名必需一致；当card_type=2时填写非法人姓名
        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 企业名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 银行编号	当card_type=0时必填， 当card_type=1或2时非必填
//            card_info.put("bank_code", hfBusinessEnterApply.getBankCode());
            // 联行号	当card_type=0时必填， 当card_type=1或2时非必填
            cardInfo.put("branch_code", hfBusinessEnterApply.getBranchCode());
            // 开户支行名称。 当card_type=0时必填， 当card_type=1或2时非必填；
//            card_info.put("branch_name", hfBusinessEnterApply.getBranchName());
        } else if (CardTypeEnum.DS.getValue().equals(cardType)) {
            // 账户名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
            cardInfo.put("cert_type", hfBusinessEnterApply.getCertType());
            // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
            cardInfo.put("cert_no", hfBusinessEnterApply.getCertNo());
            // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
            cardInfo.put("cert_validity_type", String.valueOf(hfBusinessEnterApply.getCertValidityType()));
            // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
            cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(hfBusinessEnterApply.getCertValidityType())) {
                // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
                cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertEndDate()));
            }
            // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
            cardInfo.put("mp", hfBusinessEnterApply.getMp());
            // 结算卡正面	对私结算必填。文件类型：F13
            dataMap.put("settle_card_front_pic", hfBusinessEnterApply.getSettleCardFrontPic());
            // 结算人身份证国徽面	对私结算必填。文件类型：F56；
            dataMap.put("settle_cert_back_pic", hfBusinessEnterApply.getSettleCertBackPic());
            // 结算人身份证人像面	对私结算必填。文件类型：F55；
            dataMap.put("settle_cert_front_pic", hfBusinessEnterApply.getSettleCertFrontPic());
        }
        // 结算账号	结算银行卡号，为避免资金结算失败，请正确填写；
        cardInfo.put("card_no", hfBusinessEnterApply.getCardNo());
        // 银行所在省
        cardInfo.put("prov_id", hfBusinessEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfBusinessEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 结算规则配置
//        Map<String, String> settle_config = new HashMap<>();
//        // 结算周期	D1：下个自然日到账， T1：下个工作日到账
//        settle_config.put("settle_cycle", "T1");
//        // 手续费外扣标记	1:外扣，结算时从out_settle_huifuid账户扣手续费   2:内扣，从结算金额中扣手续费，默认为内扣
//        settle_config.put("out_settle_flag", "2");
//        // 结算方式	P0：批次结算 ，P1：定时结算 批次结算指按照指定结算批次号进行资金结算，自定义时间结算是指按照商户指定到账时间进行资金结算。两种结算方式需二选一，不填默认P0：批次结算
//        settle_config.put("settle_pattern", "P0");
//        // 结算批次号	结算方式为P0：批次结算时必填，即将按指定结算批次号进行资金结算；示例值：100
//        // 0：0点昨日余额结算批次，非优先到账批则预计到账时间10:30
//        // 100：1点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 200：2点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 300：3点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 400：4点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 500：5点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30  600：6点余额结算批次，预计到账时间10:30
//        // 700：7点余额结算批次，预计到账时间10:30  800：8点余额结算批次，预计到账时间10:30
//        // 900：9点余额结算批次，预计到账时间10:30  1000：10点余额结算批次，预计到账时间14:00
//        // 1100：11点余额结算批次，预计到账时间14:00  1200：12点余额结算批次，预计到账时间14:00
//        settle_config.put("settle_batch_no", "100");
//        // 是否优先到账	当settle_pattern=P0时选填，不填默认为N，该值在结算那批次号[0-500]间生效   Y：是，N：否
//        settle_config.put("is_priority_receipt", "N");
//        dataMap.put("settle_config", settle_config);

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
//        cash_config.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.50");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_SETTLE_CONFIG_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_SETTLE_CONFIG_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_SETTLE_CONFIG_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_SETTLE_CONFIG_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用子账号开通配置接口失败", e);
        }
        return "";
    }

    // 商户基本信息修改
    public static String merchantEnterUpdateApi(HfBusinessEnterApply hfBusinessEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 汇付客户Id
        dataMap.put("huifu_id", hfBusinessEnterApply.getHfMerchantNo());
        // 商户名称，必须与商家营业执照上的名称一致；个体工商户的营业执照如没有名称、名称为“*”或空，则商户名称应填 “个体户XXX”（XXX为营业执照上经营者姓名），如“个体户张三”，汉字以2个字符计算
        dataMap.put("reg_name", hfBusinessEnterApply.getBusinessName());
        // 商户简称，需与商户注册名称相关
        dataMap.put("short_name", hfBusinessEnterApply.getBusinessShortName());
        // 小票名称
        dataMap.put("receipt_name", hfBusinessEnterApply.getBusinessShortName());
        // 公司类型 1：政府机构,2：国营企业,3：私营企业,4：外资企业,5：个体工商户,6：其它组织,7：事业单位
        Integer companyType = hfBusinessEnterApply.getCompanyType();
        if (companyType != null) {
            dataMap.put("ent_type", companyType);
        }

        dataMap.put("mcc", hfBusinessEnterApply.getMcc());
        // 经营类型	1：实体，2：虚拟
//        dataMap.put("busi_type", "1");
        // 场景类型	ONLINE：线上场景，OFFLINE：线下场景，ALL：线上线下；
        dataMap.put("scene_type", "OFFLINE");


        // 营业执照图片   文件类型：F07；
        String licensePic = hfBusinessEnterApply.getLicensePic();
        if (!StringUtils.isBlank(licensePic)) {
            dataMap.put("license_pic", licensePic);
        }

        // 营业执照编号
        String licenseCode = hfBusinessEnterApply.getLicenseCode();
        if (!StringUtils.isBlank(licenseCode)) {
            dataMap.put("license_code", licenseCode);

            // 营业执照类型	NATIONAL_LEGAL：营业执照，NATIONAL_LEGAL_MERGE：营业执照(多证合一)（默认），INST_RGST_CTF：事业单位法人证书
            dataMap.put("license_type", "NATIONAL_LEGAL_MERGE");
        }

        Integer licenseValidityType = hfBusinessEnterApply.getLicenseValidityType();
        if (licenseValidityType != null) {
            // 营业执照有效期类型	0：非长期有效 ,1：长期有效
            dataMap.put("license_validity_type", licenseValidityType);
            // 营业执照有效期开始日期  日期格式：yyyyMMdd
            dataMap.put("license_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLicenseBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(licenseValidityType)) {
                // 营业执照有效期截止日期	日期格式：yyyyMMdd
                dataMap.put("license_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLicenseEndDate()));
            }
        }

        // 成立时间	日期格式：yyyyMMdd
        String foundDate = hfBusinessEnterApply.getFoundDate();
        if (!StringUtils.isBlank(foundDate)) {
            dataMap.put("found_date", LocalDateUtil.stringToString(foundDate));
        }

        // 注册资本	保留两位小数；条件选填，国营企业、私营企业、外资企业、事业单位、其他、集体经济必填，政府机构、个体工商户可为空
        BigDecimal regCapital = hfBusinessEnterApply.getRegCapital();
        if (regCapital != null) {
            dataMap.put("reg_capital", regCapital);
        }

        // 经营范围
        String businessScope = hfBusinessEnterApply.getBusinessScope();
        if (!StringUtils.isBlank(businessScope)) {
            dataMap.put("business_scope", businessScope);
        }

        // 注册省
        String regProvinceCode = hfBusinessEnterApply.getRegProvinceCode();
        if (!StringUtils.isBlank(regProvinceCode)) {
            dataMap.put("reg_prov_id", regProvinceCode);
        }

        // 注册市
        String regCityCode = hfBusinessEnterApply.getRegCityCode();
        if (!StringUtils.isBlank(regCityCode)) {
            dataMap.put("reg_area_id", regCityCode);
        }

        // 注册区
        String regCountyCode = hfBusinessEnterApply.getRegCountyCode();
        if (!StringUtils.isBlank(regCountyCode)) {
            dataMap.put("reg_district_id", regCountyCode);
        }

        // 注册详细地址	商户注册地址或营业执照住所
        String regAddress = hfBusinessEnterApply.getRegAddress();
        if (!StringUtils.isBlank(regAddress)) {
            dataMap.put("reg_detail", regAddress);
        }

        // 经营省
        String businessProvinceCode = hfBusinessEnterApply.getBusinessProvinceCode();
        if (!StringUtils.isBlank(businessProvinceCode)) {
            dataMap.put("prov_id", businessProvinceCode);
        }

        // 经营市
        String businessCityCode = hfBusinessEnterApply.getBusinessCityCode();
        if (!StringUtils.isBlank(businessCityCode)) {
            dataMap.put("area_id", businessCityCode);
        }

        // 经营区
        String businessCountyCode = hfBusinessEnterApply.getBusinessCountyCode();
        if (!StringUtils.isBlank(businessCountyCode)) {
            dataMap.put("district_id", businessCountyCode);
        }

        // 经营详细地址
        String businessAddress = hfBusinessEnterApply.getBusinessAddress();
        if (!StringUtils.isBlank(businessAddress)) {
            businessAddress = businessAddress.replaceAll(" ", "").replaceAll("[\\t\\n\\r]", "");
            dataMap.put("detail_addr", businessAddress);
        }

        // 法人姓名
        String legalName = hfBusinessEnterApply.getLegalName();
        if (!StringUtils.isBlank(legalName)) {
            dataMap.put("legal_name", legalName);
        }

        // 法人证件类型
        String legalCertType = hfBusinessEnterApply.getLegalCertType();
        if (!StringUtils.isBlank(legalCertType)) {
            dataMap.put("legal_cert_type", legalCertType);
        }

        // 法人证件号码
        String legalCertNo = hfBusinessEnterApply.getLegalCertNo();
        if (!StringUtils.isBlank(legalCertNo)) {
            dataMap.put("legal_cert_no", legalCertNo);
        }

        // 法人证件有效期类型:0：非长期有效 ,1：长期有效
        Integer legalCertValidityType = hfBusinessEnterApply.getLegalCertValidityType();
        if (legalCertValidityType != null) {
            // 法人证件有效期类型
            dataMap.put("legal_cert_validity_type", legalCertValidityType);
            // 法人证件有效期开始日期	日期格式：yyyyMMdd
            dataMap.put("legal_cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(legalCertValidityType)) {
                // 法人证件有效期截止日期	日期格式：yyyyMMdd
                dataMap.put("legal_cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertEndDate()));
            }
        }

        // 法人手机号
        String legalMobileNo = hfBusinessEnterApply.getLegalMobileNo();
        if (!StringUtils.isBlank(legalMobileNo)) {
            dataMap.put("legal_mobile_no", legalMobileNo);
        }

        // 法人身份证地址
        String legalAddr = hfBusinessEnterApply.getLegalAddr();
        if (!StringUtils.isBlank(legalAddr)) {
            legalAddr = legalAddr.replaceAll(" ", "").replaceAll("[\\t\\n\\r]", "");
            dataMap.put("legal_addr", legalAddr);
        }

        // 法人身份证国徽面	企业商户填写。文件类型：F03
        String legalCertBackPic = hfBusinessEnterApply.getLegalCertBackPic();
        if (!StringUtils.isBlank(legalCertBackPic)) {
            dataMap.put("legal_cert_back_pic", legalCertBackPic);
        }

        // 法人身份证人像面	企业商户填写。文件类型：F02
        String legalCertFrontPic = hfBusinessEnterApply.getLegalCertFrontPic();
        if (!StringUtils.isBlank(legalCertFrontPic)) {
            dataMap.put("legal_cert_front_pic", legalCertFrontPic);
        }

        // 联系人姓名
        String contactName = hfBusinessEnterApply.getContactName();
        if (!StringUtils.isBlank(contactName)) {
            dataMap.put("contact_name", contactName);
        }

        // 联系人手机号
        String contactMobileNo = hfBusinessEnterApply.getContactMobileNo();
        if (!StringUtils.isBlank(contactMobileNo)) {
            dataMap.put("contact_mobile_no", contactMobileNo);
        }

        // 联系人电子邮箱
        String contactEmail = hfBusinessEnterApply.getContactEmail();
        if (!StringUtils.isBlank(contactEmail)) {
            dataMap.put("contact_email", contactEmail);
        }

        // 商户通知标识	入驻成功后通知商户联系人，M：发送短信通知；E：发送邮件通知；A：短信、邮件都通知；为空：不作通知
//        dataMap.put("sms_send_flag", "M");
        // 管理员账号
//        dataMap.put("login_name", "");
        // 客服电话
        String customerMobile = hfBusinessEnterApply.getCustomerMobile();
        if (!StringUtils.isBlank(customerMobile)) {
            dataMap.put("service_phone", customerMobile);
        }

        Integer cardType = hfBusinessEnterApply.getCardType();
        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        if (cardType != null) {
            cardInfo.put("card_type", String.valueOf(cardType));
        }

        // 结算账户名	当card_type=0时填写企业名称 当card_type=1时填写法人姓名，对私法人结算银行户名与法人姓名必需一致；当card_type=2时填写非法人姓名
        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 开户许可证	企业商户需要，结算账号为对公账户必填；文件类型：F08；
            dataMap.put("reg_acct_pic", hfBusinessEnterApply.getRegAcctPic());
            // 基本存款账户编号或核准号	基本存款账户信息请填写基本存款账户编号；开户许可证请填写核准号。
            dataMap.put("open_licence_no", hfBusinessEnterApply.getOpenLicenceNo());
            // 企业名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 联行号	当card_type=0时必填， 当card_type=1或2时非必填
            cardInfo.put("branch_code", hfBusinessEnterApply.getBranchCode());
        } else if (CardTypeEnum.DS.getValue().equals(cardType)) {
            // 账户名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
            cardInfo.put("cert_type", hfBusinessEnterApply.getCertType());
            // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
            cardInfo.put("cert_no", hfBusinessEnterApply.getCertNo());
            // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
            cardInfo.put("cert_validity_type", String.valueOf(hfBusinessEnterApply.getCertValidityType()));
            // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
            cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(hfBusinessEnterApply.getCertValidityType())) {
                // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
                cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertEndDate()));
            }
            // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
            cardInfo.put("mp", hfBusinessEnterApply.getMp());
            // 结算卡正面	对私结算必填。文件类型：F13
            dataMap.put("settle_card_front_pic", hfBusinessEnterApply.getSettleCardFrontPic());
            // 结算人身份证国徽面	对私结算必填。文件类型：F56；
            dataMap.put("settle_cert_back_pic", hfBusinessEnterApply.getSettleCertBackPic());
            // 结算人身份证人像面	对私结算必填。文件类型：F55；
            dataMap.put("settle_cert_front_pic", hfBusinessEnterApply.getSettleCertFrontPic());
        }
        // 结算账号	结算银行卡号，为避免资金结算失败，请正确填写；
        cardInfo.put("card_no", hfBusinessEnterApply.getCardNo());
        // 银行所在省
        cardInfo.put("prov_id", hfBusinessEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfBusinessEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 授权委托书	    对私非法人结算必填 ；文件类型：F15；
//        dataMap.put("auth_enturst_pic", hfBusinessEnterApply.getAuthEnturstPic());

        // 结算规则配置
//        Map<String, String> settle_config = new HashMap<>();
//        // 结算周期	D1：下个自然日到账， T1：下个工作日到账
//        settle_config.put("settle_cycle", "T1");
//        // 手续费外扣标记	1:外扣，结算时从out_settle_huifuid账户扣手续费   2:内扣，从结算金额中扣手续费，默认为内扣
//        settle_config.put("out_settle_flag", "2");
//        // 结算方式	P0：批次结算 ，P1：定时结算 批次结算指按照指定结算批次号进行资金结算，自定义时间结算是指按照商户指定到账时间进行资金结算。两种结算方式需二选一，不填默认P0：批次结算
//        settle_config.put("settle_pattern", "P0");
//        // 结算批次号	结算方式为P0：批次结算时必填，即将按指定结算批次号进行资金结算；示例值：100
//        // 0：0点昨日余额结算批次，非优先到账批则预计到账时间10:30
//        // 100：1点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 200：2点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 300：3点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 400：4点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 500：5点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30  600：6点余额结算批次，预计到账时间10:30
//        // 700：7点余额结算批次，预计到账时间10:30  800：8点余额结算批次，预计到账时间10:30
//        // 900：9点余额结算批次，预计到账时间10:30  1000：10点余额结算批次，预计到账时间14:00
//        // 1100：11点余额结算批次，预计到账时间14:00  1200：12点余额结算批次，预计到账时间14:00
//        settle_config.put("settle_batch_no", "100");
//        // 是否优先到账	当settle_pattern=P0时选填，不填默认为N，该值在结算那批次号[0-500]间生效   Y：是，N：否
//        settle_config.put("is_priority_receipt", "N");
//        dataMap.put("settle_config", settle_config);

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
        cashConfig.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.5");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 入驻角色类型：1-商家，2-商户
//        Integer enterType = hfBusinessEnterApply.getEnterType();
//        if (enterType == 1) {
//            // 商户身份	1：总部商户， 0：下级商户；不传默认普通商户。
//            // 商圈标记为总部商户，商圈底下的商户标记为下级商户
//            dataMap.put("head_office_flag", "1");
//        } else if (enterType == 2) {
//            // 商户身份	1：总部商户， 0：下级商户；不传默认普通商户。
//            // 商圈标记为总部商户，商圈底下的商户标记为下级商户
//            dataMap.put("head_office_flag", "0");
//            // 上级汇付Id	    如果head_office_flag=0，则字段必填，如果head_office_flag=1，上级汇付Id不可传
//            //  如果headOfficeFlag=0，useHeadInfoFlag=Y,且head_huifu_id不为空则基本信息部分复用上级的基本信息。
//            dataMap.put("head_huifu_id", hfBusinessEnterApply.getParentHfMerchantNo());
//        }

        // 使用上级资料信息	Y:是 N：否；
//        dataMap.put("use_head_info_flag", "N");
        // 商户ICP备案编号或网站许可证号；类型为PC网站时，且为企业商户，且开通快捷或网银，或大额转账，或余额支付或分账业务（20%（不含）-100%），或为个人商户开通分账业务（10%（不含）-100%），必填
        // 商家入驻必填，商户入驻不需要
        dataMap.put("mer_icp", "闽ICP备2023027415号-1X");
        // 线下经营-门头照	    文件类型：F22；
        String storeHeaderPic = hfBusinessEnterApply.getStoreHeaderPic();
        if (!StringUtils.isBlank(storeHeaderPic)) {
            dataMap.put("store_header_pic", storeHeaderPic);
        }

        // 线下经营-内景照	    文件类型：F24；
        String storeIndoorPic = hfBusinessEnterApply.getStoreIndoorPic();
        if (!StringUtils.isBlank(storeIndoorPic)) {
            dataMap.put("store_indoor_pic", storeIndoorPic);
        }

        // 线下经营-收银台	    文件类型：F105；
        String storeCashierDeskPic = hfBusinessEnterApply.getStoreCashierDeskPic();
        if (!StringUtils.isBlank(storeCashierDeskPic)) {
            dataMap.put("store_cashier_desk_pic", storeCashierDeskPic);
        }

//        // 线上经营-公司前台    线上场景提供，办公场所照片-公司前台，文件类型F478
//        dataMap.put("online_company_pic", hfBusinessEnterApply.getStoreCashierDeskPic());
//        // 线上经营-工作区域    线上场景提供，办公场所照片-工作区域，文件类型F371
//        dataMap.put("online_company_area_pic", hfBusinessEnterApply.getStoreIndoorPic());


        Map<String, Object> signUserInfo = new HashMap<>();
        // 签约人类型：1-法人，2-联系人
        Integer signUserType = hfBusinessEnterApply.getSignUserType();
        if (SignUserTypeEnum.LEGAL.getValue().equals(signUserType)) {
            // 签约人类型	 LEGAL-法人，对公结算或对私法人结算时可选法人签约；CONTACT-联系人，对公结算可选联系人（经办人）签约；OTHER-其他，对私非法人结算选“其他”，必须是结算人；
            signUserInfo.put("type", SignUserTypeEnum.LEGAL.getName());
            // 手机号	签约人类型=法人/其他 ，必填
            signUserInfo.put("mobile_no", hfBusinessEnterApply.getLegalMobileNo());
        } else if (SignUserTypeEnum.CONTACT.getValue().equals(signUserType)) {
            // 签约人类型	 LEGAL-法人，对公结算或对私法人结算时可选法人签约；CONTACT-联系人，对公结算可选联系人（经办人）签约；OTHER-其他，对私非法人结算选“其他”，必须是结算人；
            signUserInfo.put("type", SignUserTypeEnum.CONTACT.getName());
            // 身份证  签约人类型=联系人/其他，必填
            signUserInfo.put("cert_no", hfBusinessEnterApply.getContactCertNo());
        } else if (SignUserTypeEnum.OTHER.getValue().equals(signUserType)) {
            // 签约人类型	 LEGAL-法人，对公结算或对私法人结算时可选法人签约；CONTACT-联系人，对公结算可选联系人（经办人）签约；OTHER-其他，对私非法人结算选“其他”，必须是结算人；
            signUserInfo.put("type", SignUserTypeEnum.OTHER.getName());
            // 姓名   签约人类型=其他，必填；
            signUserInfo.put("name", hfBusinessEnterApply.getCardName());
            // 手机号	签约人类型=法人/其他 ，必填；注意：签约人会做姓名+身份证+手机号验证，请正确填写；
            signUserInfo.put("mobile_no", hfBusinessEnterApply.getMp());
            // 身份证  签约人类型=联系人/其他，必填；注意：签约人会做姓名+身份证+手机号验证，请正确填写
            signUserInfo.put("cert_no", hfBusinessEnterApply.getCertNo());

        }
        dataMap.put("sign_user_info", JSON.toJSONString(signUserInfo));

        // 协议信息实体
        Map<String, Object> agreementInfo = new HashMap<>();
        // 协议类型	0-电子协议 1-纸质协议 3-挂网协议
        agreementInfo.put("agreement_type", "0");
        dataMap.put("agreement_info", JSON.toJSONString(agreementInfo));

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_ENT_UPDATE_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_BASIC_DATA_MODIFY-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_BASIC_DATA_MODIFY, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_BASIC_DATA_MODIFY-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用商户基本信息修改接口失败", e);
        }
        return "";
    }

    // 企业商户基本信息入驻
    public static String merchantEnterApi(HfBusinessEnterApply hfBusinessEnterApply) {
        Map<String, String> headMap = new HashMap<>(1);
        headMap.put("Content-Type", "application/json;charset=utf-8");

        Map<String, Object> dataMap = new TreeMap<>();
        dataMap.put("req_seq_id", hfBusinessEnterApply.getReqSeqId());
        dataMap.put("req_date", hfBusinessEnterApply.getReqDate());
        // 该商户进件完成后隶属的渠道商号
        dataMap.put("upper_huifu_id", SYS_ID);
        // 商户名称，必须与商家营业执照上的名称一致；个体工商户的营业执照如没有名称、名称为“*”或空，则商户名称应填 “个体户XXX”（XXX为营业执照上经营者姓名），如“个体户张三”，汉字以2个字符计算
        dataMap.put("reg_name", hfBusinessEnterApply.getBusinessName());
        // 商户简称，需与商户注册名称相关
        dataMap.put("short_name", hfBusinessEnterApply.getBusinessShortName());
        // 小票名称
        dataMap.put("receipt_name", hfBusinessEnterApply.getBusinessShortName());
        // 公司类型 1：政府机构,2：国营企业,3：私营企业,4：外资企业,5：个体工商户,6：其它组织,7：事业单位
        dataMap.put("ent_type", hfBusinessEnterApply.getCompanyType());
        dataMap.put("mcc", hfBusinessEnterApply.getMcc());
        // 经营类型	1：实体，2：虚拟
        dataMap.put("busi_type", "1");
        // 场景类型	ONLINE：线上场景，OFFLINE：线下场景，ALL：线上线下；
        dataMap.put("scene_type", "ALL");
        // 营业执照图片   文件类型：F07；
        dataMap.put("license_pic", hfBusinessEnterApply.getLicensePic());
        // 营业执照编号
        dataMap.put("license_code", hfBusinessEnterApply.getLicenseCode());
        // 营业执照类型	NATIONAL_LEGAL：营业执照，NATIONAL_LEGAL_MERGE：营业执照(多证合一)（默认），INST_RGST_CTF：事业单位法人证书
        dataMap.put("license_type", "NATIONAL_LEGAL_MERGE");

        Integer licenseValidityType = hfBusinessEnterApply.getLicenseValidityType();
        // 营业执照有效期类型	0：非长期有效 ,1：长期有效
        dataMap.put("license_validity_type", licenseValidityType);
        // 营业执照有效期开始日期  日期格式：yyyyMMdd
        dataMap.put("license_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLicenseBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(licenseValidityType)) {
            // 营业执照有效期截止日期	日期格式：yyyyMMdd
            dataMap.put("license_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLicenseEndDate()));
        }

        // 成立时间	日期格式：yyyyMMdd
        dataMap.put("found_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getFoundDate()));
        // 注册资本	保留两位小数；条件选填，国营企业、私营企业、外资企业、事业单位、其他、集体经济必填，政府机构、个体工商户可为空
        dataMap.put("reg_capital", hfBusinessEnterApply.getRegCapital());
        // 经营范围
        dataMap.put("business_scope", hfBusinessEnterApply.getBusinessScope());
        // 注册省
        dataMap.put("reg_prov_id", hfBusinessEnterApply.getRegProvinceCode());
        // 注册市
        dataMap.put("reg_area_id", hfBusinessEnterApply.getRegCityCode());
        // 注册区
        dataMap.put("reg_district_id", hfBusinessEnterApply.getRegCountyCode());
        // 注册详细地址	商户注册地址或营业执照住所
        String regAddress = hfBusinessEnterApply.getRegAddress();
        if (!StringUtils.isBlank(regAddress)) {
            regAddress = regAddress.replaceAll("\\s", "");
            dataMap.put("reg_detail", regAddress);
        }
        // 经营省
        dataMap.put("prov_id", hfBusinessEnterApply.getBusinessProvinceCode());
        // 经营市
        dataMap.put("area_id", hfBusinessEnterApply.getBusinessCityCode());
        // 经营区
        dataMap.put("district_id", hfBusinessEnterApply.getBusinessCountyCode());
        // 经营详细地址
        String businessAddress = hfBusinessEnterApply.getBusinessAddress();
        if (!StringUtils.isBlank(businessAddress)) {
            businessAddress = businessAddress.replaceAll("\\s", "");
            dataMap.put("detail_addr", businessAddress);
        }
        // 法人姓名
        dataMap.put("legal_name", hfBusinessEnterApply.getLegalName());
        // 法人证件类型
        dataMap.put("legal_cert_type", hfBusinessEnterApply.getLegalCertType());
        // 法人证件号码
        dataMap.put("legal_cert_no", hfBusinessEnterApply.getLegalCertNo());

        Integer legalCertValidityType = hfBusinessEnterApply.getLegalCertValidityType();
        // 法人证件有效期类型
        dataMap.put("legal_cert_validity_type", legalCertValidityType);
        // 法人证件有效期开始日期	日期格式：yyyyMMdd
        dataMap.put("legal_cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertBeginDate()));
        if (CertValidityTypeEnum.NO.getValue().equals(legalCertValidityType)) {
            // 法人证件有效期截止日期	日期格式：yyyyMMdd
            dataMap.put("legal_cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getLegalCertEndDate()));
        }

        // 法人手机号
        dataMap.put("legal_mobile_no", hfBusinessEnterApply.getLegalMobileNo());
        // 法人身份证地址
        String legalAddr = hfBusinessEnterApply.getLegalAddr();
        if (!StringUtils.isBlank(legalAddr)) {
            legalAddr = legalAddr.replaceAll(" ", "").replaceAll("[\\t\\n\\r]", "");
            dataMap.put("legal_addr", legalAddr);
        }
        // 法人身份证国徽面	企业商户填写。文件类型：F03
        dataMap.put("legal_cert_back_pic", hfBusinessEnterApply.getLegalCertBackPic());
        // 法人身份证人像面	企业商户填写。文件类型：F02
        dataMap.put("legal_cert_front_pic", hfBusinessEnterApply.getLegalCertFrontPic());
        // 联系人姓名
        dataMap.put("contact_name", hfBusinessEnterApply.getContactName());
        // 联系人手机号
        dataMap.put("contact_mobile_no", hfBusinessEnterApply.getContactMobileNo());
        // 联系人电子邮箱
        dataMap.put("contact_email", hfBusinessEnterApply.getContactEmail());
        // 商户通知标识	入驻成功后通知商户联系人，M：发送短信通知；E：发送邮件通知；A：短信、邮件都通知；为空：不作通知
//        dataMap.put("sms_send_flag", "M");
        // 管理员账号
//        dataMap.put("login_name", "");
        // 客服电话
        dataMap.put("service_phone", hfBusinessEnterApply.getCustomerMobile());

        Integer cardType = hfBusinessEnterApply.getCardType();
        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 开户许可证	企业商户需要，结算账号为对公账户必填；文件类型：F08；
            dataMap.put("reg_acct_pic", hfBusinessEnterApply.getRegAcctPic());
            // 基本存款账户编号或核准号	基本存款账户信息请填写基本存款账户编号；开户许可证请填写核准号。
            dataMap.put("open_licence_no", hfBusinessEnterApply.getOpenLicenceNo());
        }

        // 结算卡信息配置
        Map<String, String> cardInfo = new HashMap<>();
        // 结算账户类型 0：对公账户 1：对私法人账户 2：对私非法人账户
        cardInfo.put("card_type", String.valueOf(cardType));
        // 结算账户名	当card_type=0时填写企业名称 当card_type=1时填写法人姓名，对私法人结算银行户名与法人姓名必需一致；当card_type=2时填写非法人姓名
        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 企业名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 联行号	当card_type=0时必填， 当card_type=1或2时非必填
            cardInfo.put("branch_code", hfBusinessEnterApply.getBranchCode());
        } else if (CardTypeEnum.DS.getValue().equals(cardType)) {
            // 账户名称
            cardInfo.put("card_name", hfBusinessEnterApply.getCardName());
            // 持卡人证件类型  当card_type=0时为空， 当card_type=1或2时必填
            cardInfo.put("cert_type", hfBusinessEnterApply.getCertType());
            // 持卡人证件号码  对私结算必填；年龄不小于18岁且不能大于80岁；如持卡人证件类型为00：身份证，则填写身份证号码 ；
            cardInfo.put("cert_no", hfBusinessEnterApply.getCertNo());
            // 持卡人证件有效期类型	    1:长期有效 0:非长期有效；
            cardInfo.put("cert_validity_type", String.valueOf(hfBusinessEnterApply.getCertValidityType()));
            // 持卡人证件有效期开始日期	    日期格式：yyyyMMdd
            cardInfo.put("cert_begin_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertBeginDate()));
            if (CertValidityTypeEnum.NO.getValue().equals(hfBusinessEnterApply.getCertValidityType())) {
                // 持卡人证件有效期截止日期	日期格式：yyyyMMdd
                cardInfo.put("cert_end_date", LocalDateUtil.stringToString(hfBusinessEnterApply.getCertEndDate()));
            }
            // 银行卡绑定手机号	11位数字，对私结算必填，开通全域资金管理功能必填；
            cardInfo.put("mp", hfBusinessEnterApply.getMp());
            // 结算卡正面	对私结算必填。文件类型：F13
            dataMap.put("settle_card_front_pic", hfBusinessEnterApply.getSettleCardFrontPic());
            // 结算人身份证国徽面	对私结算必填。文件类型：F56；
            dataMap.put("settle_cert_back_pic", hfBusinessEnterApply.getSettleCertBackPic());
            // 结算人身份证人像面	对私结算必填。文件类型：F55；
            dataMap.put("settle_cert_front_pic", hfBusinessEnterApply.getSettleCertFrontPic());
        }
        // 结算账号	结算银行卡号，为避免资金结算失败，请正确填写；
        cardInfo.put("card_no", hfBusinessEnterApply.getCardNo());
        // 银行所在省
        cardInfo.put("prov_id", hfBusinessEnterApply.getBankProvinceCode());
        // 银行所在市
        cardInfo.put("area_id", hfBusinessEnterApply.getBankCityCode());
        dataMap.put("card_info", JSON.toJSONString(cardInfo));

        // 授权委托书	    对私非法人结算必填 ；文件类型：F15；
//        dataMap.put("auth_enturst_pic", hfBusinessEnterApply.getAuthEnturstPic());

        // 结算规则配置(为空表示不自动结算)
//        Map<String, String> settle_config = new HashMap<>();
//        // 结算周期	D1：下个自然日到账， T1：下个工作日到账
//        settle_config.put("settle_cycle", "T1");
//        // 手续费外扣标记	1:外扣，结算时从out_settle_huifuid账户扣手续费   2:内扣，从结算金额中扣手续费，默认为内扣
//        settle_config.put("out_settle_flag", "2");
//        // 结算方式	P0：批次结算 ，P1：定时结算 批次结算指按照指定结算批次号进行资金结算，自定义时间结算是指按照商户指定到账时间进行资金结算。两种结算方式需二选一，不填默认P0：批次结算
//        settle_config.put("settle_pattern", "P0");
//        // 结算批次号	结算方式为P0：批次结算时必填，即将按指定结算批次号进行资金结算；示例值：100
//        // 0：0点昨日余额结算批次，非优先到账批则预计到账时间10:30
//        // 100：1点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 200：2点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 300：3点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30 400：4点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30
//        // 500：5点余额结算批次，优先到账则预计到账时间06:50，非优先到账批则预计到账时间10:30  600：6点余额结算批次，预计到账时间10:30
//        // 700：7点余额结算批次，预计到账时间10:30  800：8点余额结算批次，预计到账时间10:30
//        // 900：9点余额结算批次，预计到账时间10:30  1000：10点余额结算批次，预计到账时间14:00
//        // 1100：11点余额结算批次，预计到账时间14:00  1200：12点余额结算批次，预计到账时间14:00
//        settle_config.put("settle_batch_no", "100");
//        // 是否优先到账	当settle_pattern=P0时选填，不填默认为N，该值在结算那批次号[0-500]间生效   Y：是，N：否
//        settle_config.put("is_priority_receipt", "N");
//        dataMap.put("settle_config", settle_config);

        // 取现规则配置
        List<Map<String, String>> cashConfigs = new ArrayList<>();
        Map<String, String> cashConfig = new HashMap<>();
        // 取现类型	D0：当日到账；当日交易资金当天可取现到账； T1：下个工作日到账; D1：下个自然日到账; DM：当日到账；到账资金不包括当天的交易资金
        cashConfig.put("cash_type", "T1");
        // 取现固定手续费（元）   fix_amt与fee_rate至少填写一项，需保留小数点后两位，不收费请填写0.00
        cashConfig.put("fix_amt", "0.00");
        // 取现手续费率（%）    fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00
        // 注：如果fix_amt与fee_rate都填写了则手续费=fix_amt+支付金额*fee_rate
        cashConfig.put("fee_rate", "0.5");
        // 是否交易手续费外扣	1:外扣 2:内扣（默认2内扣）
        cashConfig.put("out_fee_flag", "2");
        // 是否优先到账	Y：是 ，N：否。不填，默认值为否。仅在取现类型配置为D1 和 T1 时生效
        cashConfig.put("is_priority_receipt", "Y");
        cashConfigs.add(cashConfig);
        dataMap.put("cash_config", JSON.toJSONString(cashConfigs));

        // 如果是商户入驻走的是企业入驻，则商户身份不传
        // 商户身份	1：总部商户， 0：下级商户；不传默认普通商户。
        // 入驻角色类型：1-商家，2-商户
        Integer enterType = hfBusinessEnterApply.getEnterType();
        if (enterType == 1) {
            // 商户身份	1：总部商户， 0：下级商户；不传默认普通商户。
            // 商圈标记为总部商户，商圈底下的商户标记为下级商户
            dataMap.put("head_office_flag", "1");
        } else if (enterType == 2) {
            // 商户身份	1：总部商户， 0：下级商户；不传默认普通商户。
            // 商圈标记为总部商户，商圈底下的商户标记为下级商户
//            dataMap.put("head_office_flag", "0");
            // 上级汇付Id	    如果head_office_flag=0，则字段必填，如果head_office_flag=1，上级汇付Id不可传
            //  如果headOfficeFlag=0，useHeadInfoFlag=Y,且head_huifu_id不为空则基本信息部分复用上级的基本信息。
//            dataMap.put("head_huifu_id", hfBusinessEnterApply.getParentHfMerchantNo());
        }


        // 使用上级资料信息	Y:是 N：否；
        dataMap.put("use_head_info_flag", "N");
        // 商户ICP备案编号或网站许可证号；类型为PC网站时，且为企业商户，且开通快捷或网银，或大额转账，或余额支付或分账业务（20%（不含）-100%），或为个人商户开通分账业务（10%（不含）-100%），必填
        // 商家入驻必填，商户入驻不需要
        dataMap.put("mer_icp", "闽ICP备2023027415号-1X");
        // 线下经营-门头照	    文件类型：F22；
        dataMap.put("store_header_pic", hfBusinessEnterApply.getStoreHeaderPic());
        // 线下经营-内景照	    文件类型：F24；
        dataMap.put("store_indoor_pic", hfBusinessEnterApply.getStoreIndoorPic());
        // 线下经营-收银台	    文件类型：F105；
        dataMap.put("store_cashier_desk_pic", hfBusinessEnterApply.getStoreCashierDeskPic());
        // 线上经营-公司前台    线上场景提供，办公场所照片-公司前台，文件类型F478
        dataMap.put("online_company_pic", hfBusinessEnterApply.getStoreCashierDeskPic());
        // 线上经营-工作区域    线上场景提供，办公场所照片-工作区域，文件类型F371
        dataMap.put("online_company_area_pic", hfBusinessEnterApply.getStoreIndoorPic());

        // 补充文件信息
        if (CertTypeEnum.GATTBTXZ.getValue().equals(hfBusinessEnterApply.getLegalCertType())
                || CertTypeEnum.TBZ.getValue().equals(hfBusinessEnterApply.getLegalCertType())) {
            List<Map<String, Object>> extendedMaterialList = new ArrayList<>();
            Map<String, Object> extendedMaterialMap = new HashMap<>();
            extendedMaterialMap.put("file_id", hfBusinessEnterApply.getLegalCertFrontPic());
            extendedMaterialMap.put("file_type", HfFileTypeEnum.FR_GAT_TXZ_ZM.getValue());
            extendedMaterialList.add(extendedMaterialMap);

            dataMap.put("extended_material_list", JSON.toJSONString(extendedMaterialList));
        } else if (CertTypeEnum.WGHZ.getValue().equals(hfBusinessEnterApply.getLegalCertType())) {
            List<Map<String, Object>> extendedMaterialList = new ArrayList<>();
            Map<String, Object> extendedMaterialMap = new HashMap<>();
            extendedMaterialMap.put("file_id", hfBusinessEnterApply.getLegalCertFrontPic());
            extendedMaterialMap.put("file_type", HfFileTypeEnum.WG_HZ_ZM.getValue());
            extendedMaterialList.add(extendedMaterialMap);

            dataMap.put("extended_material_list", JSON.toJSONString(extendedMaterialList));
        } else if (CertTypeEnum.WGRJLZ.getValue().equals(hfBusinessEnterApply.getLegalCertType())) {
            List<Map<String, Object>> extendedMaterialList = new ArrayList<>();
            Map<String, Object> extendedMaterialMap = new HashMap<>();
            extendedMaterialMap.put("file_id", hfBusinessEnterApply.getLegalCertFrontPic());
            extendedMaterialMap.put("file_type", HfFileTypeEnum.WGR_JLZ.getValue());
            extendedMaterialList.add(extendedMaterialMap);

            dataMap.put("extended_material_list", JSON.toJSONString(extendedMaterialList));
        } else if (CertTypeEnum.GATJZZ.getValue().equals(hfBusinessEnterApply.getLegalCertType())) {
            List<Map<String, Object>> extendedMaterialList = new ArrayList<>();
            Map<String, Object> extendedMaterialMap = new HashMap<>();
            extendedMaterialMap.put("file_id", hfBusinessEnterApply.getLegalCertFrontPic());
            extendedMaterialMap.put("file_type", HfFileTypeEnum.GAT_JZZ.getValue());
            extendedMaterialList.add(extendedMaterialMap);

            dataMap.put("extended_material_list", JSON.toJSONString(extendedMaterialList));
        }

        // 异步请求地址	审核结果消息接收地址，为空时不推送消息；
        dataMap.put("async_return_url", DynamicCommonConfig.DOMAIN_URL + HfConstant.MERCHANT_ENT_AUDIT_NOTIFY_URL);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("sys_id", SYS_ID);
        paramMap.put("product_id", PRODUCT_ID);
        paramMap.put("data", dataMap);
        paramMap.put("sign", sign(JSON.toJSONString(dataMap)));

        String requestJson = JSON.toJSONString(paramMap);
        log.info("MERCHANT_ENT_API-request:{}", requestJson);
        try {
            HttpResponse httpResponse = HttpUtils.doPost(MERCHANT_ENT_API, "", headMap, new HashMap<>(), requestJson);
            String result = EntityUtils.toString(httpResponse.getEntity());
            log.info("MERCHANT_ENT_API-result:{}", result);
            return result;
        } catch (Exception e) {
            log.error("调用企业商户基本信息入驻接口失败", e);
        }
        return "";
    }

    // 图片上传
    public static String imgUploadApi(File file, String type) {
        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");

        // 请求参数
        Map<String, Object> params = new HashMap<>();
        // 请求流水号，需保证当天商户下唯一，推荐采用日期时间+几位流水号的形式
        params.put("req_seq_id", yyyyMMddHHmmss + GenerateUtil.getRandomNum(5));
        params.put("req_date", yyyyMMdd);
        params.put("file_type", type);
        //如果商户还未成功进件huifu_id可以为空
//        params.put("huifu_id", "6666000132294252");
        String data = JSON.toJSONString(params);

        CloseableHttpClient httpclient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost(IMG_UPLOAD_API);
        ContentType contentType = ContentType.create("text/plain", StandardCharsets.UTF_8);
        MultipartEntityBuilder mEntityBuilder = MultipartEntityBuilder.create();
        mEntityBuilder.addTextBody("sys_id", SYS_ID, contentType);
        mEntityBuilder.addTextBody("product_id", PRODUCT_ID, contentType);
        mEntityBuilder.addTextBody("data", data, contentType);
        mEntityBuilder.addBinaryBody("file", file);

        httpPost.setEntity(mEntityBuilder.build());
        try {
            CloseableHttpResponse response = httpclient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity resEntity = response.getEntity();
                String result = EntityUtils.toString(resEntity);
                JSONObject jsonObject = JSON.parseObject(result);
                JSONObject dataJsonObject = jsonObject.getJSONObject("data");
                return dataJsonObject.getString("file_id");
            }
            log.error("调用汇付图片上传接口失败");
        } catch (Exception e) {
            log.error("上传图片到汇付失败");
        }

        return null;
    }

    public static String sign(String data) {
        return sign(data, PRIVATE_SECRET);
    }

    /**
     * RSA私钥签名：签名方式SHA256WithRSA
     *
     * @param data             待签名字符串
     * @param privateKeyBase64 私钥（Base64编码）
     * @return 签名byte[]
     * @throws Exception
     */
    public static String sign(String data, String privateKeyBase64) {
        // Base64 --> Key
        try {
            byte[] bytes = Base64.getDecoder().decode(privateKeyBase64);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // Sign
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateKey);
            signature.update(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            return null;
        }
    }


    public static boolean verify(String data, String sign) {
        return verify(data, HF_PUBLIC_SECRET, sign);
    }

    /**
     * 使用汇付RSA公钥验签
     *
     * @param data            待签名字符串
     * @param publicKeyBase64 公钥（Base64编码）
     * @return 验签结果
     * @throws Exception
     */
    public static boolean verify(String data, String publicKeyBase64, String sign) {
        // Base64 --> Key
        try {
            byte[] bytes = Base64.getDecoder().decode(publicKeyBase64);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            // verify
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initVerify(publicKey);
            signature.update(data.getBytes(StandardCharsets.UTF_8));
            return signature.verify(Base64.getDecoder().decode(sign));
        } catch (Exception e) {
            log.error("Exception", e);
            return false;
        }

    }


}
